Embedded JavaScript virtual machine
Dependents: DISCO-F469NI_javascript_blinker
v7.c@2:7762b98d31c7, 2016-10-11 (annotated)
- Committer:
- Marko Mikulicic
- Date:
- Tue Oct 11 12:22:24 2016 +0200
- Revision:
- 2:7762b98d31c7
- Parent:
- 1:887cf63a2a0b
- Child:
- 3:2bce515c5f0b
Make v7 cpp-safe
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Marko Mikulicic |
0:c0ecb8bf28eb | 1 | #include "v7.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 3 | #line 1 "v7/src/license.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6 | * Copyright (c) 2013-2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 8 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 9 | * This software is dual-licensed: you can redistribute it and/or modify |
Marko Mikulicic |
0:c0ecb8bf28eb | 10 | * it under the terms of the GNU General Public License version 2 as |
Marko Mikulicic |
0:c0ecb8bf28eb | 11 | * published by the Free Software Foundation. For the terms of this |
Marko Mikulicic |
0:c0ecb8bf28eb | 12 | * license, see <http://www.gnu.org/licenses/>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14 | * You are free to use this software under the terms of the GNU General |
Marko Mikulicic |
0:c0ecb8bf28eb | 15 | * Public License, but WITHOUT ANY WARRANTY; without even the implied |
Marko Mikulicic |
0:c0ecb8bf28eb | 16 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17 | * See the GNU General Public License for more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 19 | * Alternatively, you can license this software under a commercial |
Marko Mikulicic |
0:c0ecb8bf28eb | 20 | * license, as set out in <https://www.cesanta.com/license>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23 | #ifdef V7_EXPOSE_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 24 | #define V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 25 | #define V7_EXTERN extern |
Marko Mikulicic |
0:c0ecb8bf28eb | 26 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 27 | #define V7_PRIVATE static |
Marko Mikulicic |
0:c0ecb8bf28eb | 28 | #define V7_EXTERN static |
Marko Mikulicic |
0:c0ecb8bf28eb | 29 | #endif /* CS_V7_SRC_LICENSE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 31 | #line 1 "common/platform.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 32 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33 | #ifndef CS_COMMON_PLATFORM_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34 | #define CS_COMMON_PLATFORM_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 35 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 36 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 37 | * For the "custom" platform, includes and dependencies can be |
Marko Mikulicic |
0:c0ecb8bf28eb | 38 | * provided through mg_locals.h. |
Marko Mikulicic |
0:c0ecb8bf28eb | 39 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 40 | #define CS_P_CUSTOM 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 41 | #define CS_P_UNIX 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 42 | #define CS_P_WINDOWS 2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 43 | #define CS_P_ESP_LWIP 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 44 | #define CS_P_CC3200 4 |
Marko Mikulicic |
0:c0ecb8bf28eb | 45 | #define CS_P_MSP432 5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 46 | #define CS_P_CC3100 6 |
Marko Mikulicic |
1:887cf63a2a0b | 47 | #define CS_P_MBED 7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 48 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 49 | /* If not specified explicitly, we guess platform by defines. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 50 | #ifndef CS_PLATFORM |
Marko Mikulicic |
0:c0ecb8bf28eb | 51 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 52 | #if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__) |
Marko Mikulicic |
0:c0ecb8bf28eb | 53 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 54 | #define CS_PLATFORM CS_P_MSP432 |
Marko Mikulicic |
0:c0ecb8bf28eb | 55 | #elif defined(cc3200) |
Marko Mikulicic |
0:c0ecb8bf28eb | 56 | #define CS_PLATFORM CS_P_CC3200 |
Marko Mikulicic |
0:c0ecb8bf28eb | 57 | #elif defined(__unix__) || defined(__APPLE__) |
Marko Mikulicic |
0:c0ecb8bf28eb | 58 | #define CS_PLATFORM CS_P_UNIX |
Marko Mikulicic |
0:c0ecb8bf28eb | 59 | #elif defined(_WIN32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 60 | #define CS_PLATFORM CS_P_WINDOWS |
Marko Mikulicic |
1:887cf63a2a0b | 61 | #elif defined(__MBED__) |
Marko Mikulicic |
1:887cf63a2a0b | 62 | #define CS_PLATFORM CS_P_MBED |
Marko Mikulicic |
0:c0ecb8bf28eb | 63 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 64 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 65 | #ifndef CS_PLATFORM |
Marko Mikulicic |
0:c0ecb8bf28eb | 66 | #error "CS_PLATFORM is not specified and we couldn't guess it." |
Marko Mikulicic |
0:c0ecb8bf28eb | 67 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 68 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 69 | #endif /* !defined(CS_PLATFORM) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 70 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 71 | /* Amalgamated: #include "common/platforms/platform_unix.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 72 | /* Amalgamated: #include "common/platforms/platform_windows.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 73 | /* Amalgamated: #include "common/platforms/platform_esp_lwip.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 74 | /* Amalgamated: #include "common/platforms/platform_cc3200.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 75 | /* Amalgamated: #include "common/platforms/platform_cc3100.h" */ |
Marko Mikulicic |
1:887cf63a2a0b | 76 | /* Amalgamated: #include "common/platforms/platform_mbed.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 77 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 78 | /* Common stuff */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 79 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 80 | #ifdef __GNUC__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 81 | #define NORETURN __attribute__((noreturn)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 82 | #define NOINLINE __attribute__((noinline)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 83 | #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 84 | #define NOINSTR __attribute__((no_instrument_function)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 85 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 86 | #define NORETURN |
Marko Mikulicic |
0:c0ecb8bf28eb | 87 | #define NOINLINE |
Marko Mikulicic |
0:c0ecb8bf28eb | 88 | #define WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 89 | #define NOINSTR |
Marko Mikulicic |
0:c0ecb8bf28eb | 90 | #endif /* __GNUC__ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 91 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 92 | #ifndef ARRAY_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 93 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) |
Marko Mikulicic |
0:c0ecb8bf28eb | 94 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 95 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 96 | #endif /* CS_COMMON_PLATFORM_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 97 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 98 | #line 1 "common/platforms/platform_windows.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 99 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 100 | #ifndef CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 101 | #define CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 102 | #if CS_PLATFORM == CS_P_WINDOWS |
Marko Mikulicic |
0:c0ecb8bf28eb | 103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 104 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 105 | * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) |
Marko Mikulicic |
0:c0ecb8bf28eb | 106 | * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) |
Marko Mikulicic |
0:c0ecb8bf28eb | 107 | * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) |
Marko Mikulicic |
0:c0ecb8bf28eb | 108 | * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) |
Marko Mikulicic |
0:c0ecb8bf28eb | 109 | * MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) |
Marko Mikulicic |
0:c0ecb8bf28eb | 110 | * MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) |
Marko Mikulicic |
0:c0ecb8bf28eb | 111 | * MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003) |
Marko Mikulicic |
0:c0ecb8bf28eb | 112 | * MSVC++ 7.0 _MSC_VER == 1300 |
Marko Mikulicic |
0:c0ecb8bf28eb | 113 | * MSVC++ 6.0 _MSC_VER == 1200 |
Marko Mikulicic |
0:c0ecb8bf28eb | 114 | * MSVC++ 5.0 _MSC_VER == 1100 |
Marko Mikulicic |
0:c0ecb8bf28eb | 115 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 116 | #ifdef _MSC_VER |
Marko Mikulicic |
0:c0ecb8bf28eb | 117 | #pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 118 | #pragma warning(disable : 4204) /* missing c99 support */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 119 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 121 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 122 | #define _CRT_SECURE_NO_WARNINGS |
Marko Mikulicic |
0:c0ecb8bf28eb | 123 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 124 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 125 | #include <direct.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 126 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 127 | #include <fcntl.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 128 | #include <io.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 129 | #include <limits.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 130 | #include <signal.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 131 | #include <stddef.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 132 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 133 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 134 | #include <sys/stat.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 135 | #include <time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 136 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 137 | #ifdef _MSC_VER |
Marko Mikulicic |
0:c0ecb8bf28eb | 138 | #pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 139 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 141 | #include <winsock2.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 142 | #include <ws2tcpip.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 143 | #include <windows.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 144 | #include <process.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 146 | #if defined(_MSC_VER) && _MSC_VER >= 1800 |
Marko Mikulicic |
0:c0ecb8bf28eb | 147 | #define strdup _strdup |
Marko Mikulicic |
0:c0ecb8bf28eb | 148 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 150 | #ifndef EINPROGRESS |
Marko Mikulicic |
0:c0ecb8bf28eb | 151 | #define EINPROGRESS WSAEINPROGRESS |
Marko Mikulicic |
0:c0ecb8bf28eb | 152 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 153 | #ifndef EWOULDBLOCK |
Marko Mikulicic |
0:c0ecb8bf28eb | 154 | #define EWOULDBLOCK WSAEWOULDBLOCK |
Marko Mikulicic |
0:c0ecb8bf28eb | 155 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 156 | #ifndef __func__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 157 | #define STRX(x) #x |
Marko Mikulicic |
0:c0ecb8bf28eb | 158 | #define STR(x) STRX(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 159 | #define __func__ __FILE__ ":" STR(__LINE__) |
Marko Mikulicic |
0:c0ecb8bf28eb | 160 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 161 | #define snprintf _snprintf |
Marko Mikulicic |
0:c0ecb8bf28eb | 162 | #define fileno _fileno |
Marko Mikulicic |
0:c0ecb8bf28eb | 163 | #define vsnprintf _vsnprintf |
Marko Mikulicic |
0:c0ecb8bf28eb | 164 | #define sleep(x) Sleep((x) *1000) |
Marko Mikulicic |
0:c0ecb8bf28eb | 165 | #define to64(x) _atoi64(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 166 | #if !defined(__MINGW32__) && !defined(__MINGW64__) |
Marko Mikulicic |
0:c0ecb8bf28eb | 167 | #define popen(x, y) _popen((x), (y)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 168 | #define pclose(x) _pclose(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 169 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 170 | #define rmdir _rmdir |
Marko Mikulicic |
0:c0ecb8bf28eb | 171 | #if defined(_MSC_VER) && _MSC_VER >= 1400 |
Marko Mikulicic |
0:c0ecb8bf28eb | 172 | #define fseeko(x, y, z) _fseeki64((x), (y), (z)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 173 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 174 | #define fseeko(x, y, z) fseek((x), (y), (z)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 175 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 176 | #if defined(_MSC_VER) && _MSC_VER <= 1200 |
Marko Mikulicic |
0:c0ecb8bf28eb | 177 | typedef unsigned long uintptr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 178 | typedef long intptr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 179 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 180 | typedef int socklen_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 181 | #if _MSC_VER >= 1700 |
Marko Mikulicic |
0:c0ecb8bf28eb | 182 | #include <stdint.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 183 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 184 | typedef signed char int8_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 185 | typedef unsigned char uint8_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 186 | typedef int int32_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 187 | typedef unsigned int uint32_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 188 | typedef short int16_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 189 | typedef unsigned short uint16_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 190 | typedef __int64 int64_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 191 | typedef unsigned __int64 uint64_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 192 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 193 | typedef SOCKET sock_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 194 | typedef uint32_t in_addr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 195 | #ifndef UINT16_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 196 | #define UINT16_MAX 65535 |
Marko Mikulicic |
0:c0ecb8bf28eb | 197 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 198 | #ifndef UINT32_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 199 | #define UINT32_MAX 4294967295 |
Marko Mikulicic |
0:c0ecb8bf28eb | 200 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 201 | #ifndef pid_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 202 | #define pid_t HANDLE |
Marko Mikulicic |
0:c0ecb8bf28eb | 203 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 204 | #define INT64_FMT "I64d" |
Marko Mikulicic |
0:c0ecb8bf28eb | 205 | #define INT64_X_FMT "I64x" |
Marko Mikulicic |
0:c0ecb8bf28eb | 206 | #define SIZE_T_FMT "Iu" |
Marko Mikulicic |
0:c0ecb8bf28eb | 207 | #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) |
Marko Mikulicic |
0:c0ecb8bf28eb | 208 | typedef struct stat cs_stat_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 209 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 210 | typedef struct _stati64 cs_stat_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 211 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 212 | #ifndef S_ISDIR |
Marko Mikulicic |
0:c0ecb8bf28eb | 213 | #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR) |
Marko Mikulicic |
0:c0ecb8bf28eb | 214 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 215 | #ifndef S_ISREG |
Marko Mikulicic |
0:c0ecb8bf28eb | 216 | #define S_ISREG(x) (((x) &_S_IFMT) == _S_IFREG) |
Marko Mikulicic |
0:c0ecb8bf28eb | 217 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 218 | #define DIRSEP '\\' |
Marko Mikulicic |
0:c0ecb8bf28eb | 219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 220 | #ifndef va_copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 221 | #ifdef __va_copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 222 | #define va_copy __va_copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 223 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 224 | #define va_copy(x, y) (x) = (y) |
Marko Mikulicic |
0:c0ecb8bf28eb | 225 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 226 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 228 | #ifndef MG_MAX_HTTP_REQUEST_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 229 | #define MG_MAX_HTTP_REQUEST_SIZE 8192 |
Marko Mikulicic |
0:c0ecb8bf28eb | 230 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 232 | #ifndef MG_MAX_HTTP_SEND_MBUF |
Marko Mikulicic |
0:c0ecb8bf28eb | 233 | #define MG_MAX_HTTP_SEND_MBUF 4096 |
Marko Mikulicic |
0:c0ecb8bf28eb | 234 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 236 | #ifndef MG_MAX_HTTP_HEADERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 237 | #define MG_MAX_HTTP_HEADERS 40 |
Marko Mikulicic |
0:c0ecb8bf28eb | 238 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 239 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 240 | #endif /* CS_PLATFORM == CS_P_WINDOWS */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 241 | #endif /* CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 242 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 243 | #line 1 "common/platforms/platform_unix.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 244 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 245 | #ifndef CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 246 | #define CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 247 | #if CS_PLATFORM == CS_P_UNIX |
Marko Mikulicic |
0:c0ecb8bf28eb | 248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 249 | #ifndef _XOPEN_SOURCE |
Marko Mikulicic |
0:c0ecb8bf28eb | 250 | #define _XOPEN_SOURCE 600 |
Marko Mikulicic |
0:c0ecb8bf28eb | 251 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 253 | /* <inttypes.h> wants this for C++ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 254 | #ifndef __STDC_FORMAT_MACROS |
Marko Mikulicic |
0:c0ecb8bf28eb | 255 | #define __STDC_FORMAT_MACROS |
Marko Mikulicic |
0:c0ecb8bf28eb | 256 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 257 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 258 | /* C++ wants that for INT64_MAX */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 259 | #ifndef __STDC_LIMIT_MACROS |
Marko Mikulicic |
0:c0ecb8bf28eb | 260 | #define __STDC_LIMIT_MACROS |
Marko Mikulicic |
0:c0ecb8bf28eb | 261 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 263 | /* Enable fseeko() and ftello() functions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 264 | #ifndef _LARGEFILE_SOURCE |
Marko Mikulicic |
0:c0ecb8bf28eb | 265 | #define _LARGEFILE_SOURCE |
Marko Mikulicic |
0:c0ecb8bf28eb | 266 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 268 | /* Enable 64-bit file offsets */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 269 | #ifndef _FILE_OFFSET_BITS |
Marko Mikulicic |
0:c0ecb8bf28eb | 270 | #define _FILE_OFFSET_BITS 64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 271 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 272 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 273 | #include <arpa/inet.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 274 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 275 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 276 | #include <dirent.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 277 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 278 | #include <fcntl.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 279 | #include <inttypes.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 280 | #include <stdint.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 281 | #include <limits.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 282 | #include <math.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 283 | #include <netdb.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 284 | #include <netinet/in.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 285 | #include <pthread.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 286 | #include <signal.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 287 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 288 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 289 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 290 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 291 | #include <sys/socket.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 292 | #include <sys/select.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 293 | #include <sys/stat.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 294 | #include <sys/time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 295 | #include <sys/types.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 296 | #include <unistd.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 298 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 299 | * osx correctly avoids defining strtoll when compiling in strict ansi mode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 300 | * We require strtoll, and if your embedded pre-c99 compiler lacks one, please |
Marko Mikulicic |
0:c0ecb8bf28eb | 301 | * implement a shim. |
Marko Mikulicic |
0:c0ecb8bf28eb | 302 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 303 | #if !(defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L) |
Marko Mikulicic |
0:c0ecb8bf28eb | 304 | long long strtoll(const char *, char **, int); |
Marko Mikulicic |
0:c0ecb8bf28eb | 305 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 307 | typedef int sock_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 308 | #define INVALID_SOCKET (-1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 309 | #define SIZE_T_FMT "zu" |
Marko Mikulicic |
0:c0ecb8bf28eb | 310 | typedef struct stat cs_stat_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 311 | #define DIRSEP '/' |
Marko Mikulicic |
0:c0ecb8bf28eb | 312 | #define to64(x) strtoll(x, NULL, 10) |
Marko Mikulicic |
0:c0ecb8bf28eb | 313 | #define INT64_FMT PRId64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 314 | #define INT64_X_FMT PRIx64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 316 | #ifndef __cdecl |
Marko Mikulicic |
0:c0ecb8bf28eb | 317 | #define __cdecl |
Marko Mikulicic |
0:c0ecb8bf28eb | 318 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 320 | #ifndef va_copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 321 | #ifdef __va_copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 322 | #define va_copy __va_copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 323 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 324 | #define va_copy(x, y) (x) = (y) |
Marko Mikulicic |
0:c0ecb8bf28eb | 325 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 326 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 328 | #define closesocket(x) close(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 330 | #ifndef MG_MAX_HTTP_REQUEST_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 331 | #define MG_MAX_HTTP_REQUEST_SIZE 8192 |
Marko Mikulicic |
0:c0ecb8bf28eb | 332 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 334 | #ifndef MG_MAX_HTTP_SEND_MBUF |
Marko Mikulicic |
0:c0ecb8bf28eb | 335 | #define MG_MAX_HTTP_SEND_MBUF 4096 |
Marko Mikulicic |
0:c0ecb8bf28eb | 336 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 338 | #ifndef MG_MAX_HTTP_HEADERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 339 | #define MG_MAX_HTTP_HEADERS 40 |
Marko Mikulicic |
0:c0ecb8bf28eb | 340 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 342 | #endif /* CS_PLATFORM == CS_P_UNIX */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 343 | #endif /* CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 344 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 345 | #line 1 "common/platforms/platform_esp_lwip.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 346 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 347 | #ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 348 | #define CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 349 | #if CS_PLATFORM == CS_P_ESP_LWIP |
Marko Mikulicic |
0:c0ecb8bf28eb | 350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 351 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 352 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 353 | #include <fcntl.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 354 | #include <inttypes.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 355 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 356 | #include <sys/stat.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 357 | #include <sys/time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 358 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 359 | #include <lwip/err.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 360 | #include <lwip/ip_addr.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 361 | #include <lwip/inet.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 362 | #include <lwip/netdb.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 363 | #include <lwip/dns.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 365 | #ifndef LWIP_PROVIDE_ERRNO |
Marko Mikulicic |
0:c0ecb8bf28eb | 366 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 367 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 369 | #define LWIP_TIMEVAL_PRIVATE 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 371 | #if LWIP_SOCKET |
Marko Mikulicic |
0:c0ecb8bf28eb | 372 | #include <lwip/sockets.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 373 | #define SOMAXCONN 10 |
Marko Mikulicic |
0:c0ecb8bf28eb | 374 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 375 | /* We really need the definitions from sockets.h. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 376 | #undef LWIP_SOCKET |
Marko Mikulicic |
0:c0ecb8bf28eb | 377 | #define LWIP_SOCKET 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 378 | #include <lwip/sockets.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 379 | #undef LWIP_SOCKET |
Marko Mikulicic |
0:c0ecb8bf28eb | 380 | #define LWIP_SOCKET 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 381 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 383 | typedef int sock_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 384 | #define INVALID_SOCKET (-1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 385 | #define SIZE_T_FMT "u" |
Marko Mikulicic |
0:c0ecb8bf28eb | 386 | typedef struct stat cs_stat_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 387 | #define DIRSEP '/' |
Marko Mikulicic |
0:c0ecb8bf28eb | 388 | #define to64(x) strtoll(x, NULL, 10) |
Marko Mikulicic |
0:c0ecb8bf28eb | 389 | #define INT64_FMT PRId64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 390 | #define INT64_X_FMT PRIx64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 391 | #define __cdecl |
Marko Mikulicic |
0:c0ecb8bf28eb | 392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 393 | unsigned long os_random(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 394 | #define random os_random |
Marko Mikulicic |
0:c0ecb8bf28eb | 395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 396 | #endif /* CS_PLATFORM == CS_P_ESP_LWIP */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 397 | #endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 398 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 399 | #line 1 "common/mbuf.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 400 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 401 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 402 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 403 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 404 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 406 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 407 | * === Memory Buffers |
Marko Mikulicic |
0:c0ecb8bf28eb | 408 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 409 | * Mbufs are mutable/growing memory buffers, like C++ strings. |
Marko Mikulicic |
0:c0ecb8bf28eb | 410 | * Mbuf can append data to the end of a buffer or insert data into arbitrary |
Marko Mikulicic |
0:c0ecb8bf28eb | 411 | * position in the middle of a buffer. The buffer grows automatically when |
Marko Mikulicic |
0:c0ecb8bf28eb | 412 | * needed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 413 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 415 | #ifndef CS_COMMON_MBUF_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 416 | #define CS_COMMON_MBUF_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 417 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 418 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 419 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 420 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 422 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 424 | #ifndef MBUF_SIZE_MULTIPLIER |
Marko Mikulicic |
0:c0ecb8bf28eb | 425 | #define MBUF_SIZE_MULTIPLIER 1.5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 426 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 428 | /* Memory buffer descriptor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 429 | struct mbuf { |
Marko Mikulicic |
0:c0ecb8bf28eb | 430 | char *buf; /* Buffer pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 431 | size_t len; /* Data length. Data is located between offset 0 and len. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 432 | size_t size; /* Buffer size allocated by realloc(1). Must be >= len */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 433 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 434 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 435 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 436 | * Initialises an Mbuf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 437 | * `initial_capacity` specifies the initial capacity of the mbuf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 438 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 439 | void mbuf_init(struct mbuf *, size_t initial_capacity); |
Marko Mikulicic |
0:c0ecb8bf28eb | 440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 441 | /* Frees the space allocated for the mbuffer and resets the mbuf structure. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 442 | void mbuf_free(struct mbuf *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 443 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 444 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 445 | * Appends data to the Mbuf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 446 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 447 | * Returns the number of bytes appended or 0 if out of memory. |
Marko Mikulicic |
0:c0ecb8bf28eb | 448 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 449 | size_t mbuf_append(struct mbuf *, const void *data, size_t data_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 451 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 452 | * Inserts data at a specified offset in the Mbuf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 453 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 454 | * Existing data will be shifted forwards and the buffer will |
Marko Mikulicic |
0:c0ecb8bf28eb | 455 | * be grown if necessary. |
Marko Mikulicic |
0:c0ecb8bf28eb | 456 | * Returns the number of bytes inserted. |
Marko Mikulicic |
0:c0ecb8bf28eb | 457 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 458 | size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 460 | /* Removes `data_size` bytes from the beginning of the buffer. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 461 | void mbuf_remove(struct mbuf *, size_t data_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 463 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 464 | * Resizes an Mbuf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 465 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 466 | * If `new_size` is smaller than buffer's `len`, the |
Marko Mikulicic |
0:c0ecb8bf28eb | 467 | * resize is not performed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 468 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 469 | void mbuf_resize(struct mbuf *, size_t new_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 471 | /* Shrinks an Mbuf by resizing its `size` to `len`. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 472 | void mbuf_trim(struct mbuf *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 474 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 475 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 476 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 478 | #endif /* CS_COMMON_MBUF_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 479 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 480 | #line 1 "common/platforms/simplelink/cs_simplelink.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 481 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 482 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 483 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 484 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 485 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 486 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 487 | #ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 488 | #define CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 490 | /* If simplelink.h is already included, all bets are off. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 491 | #if defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__) |
Marko Mikulicic |
0:c0ecb8bf28eb | 492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 493 | #include <stdbool.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 494 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 495 | #ifndef __TI_COMPILER_VERSION__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 496 | #undef __CONCAT |
Marko Mikulicic |
0:c0ecb8bf28eb | 497 | #undef FD_CLR |
Marko Mikulicic |
0:c0ecb8bf28eb | 498 | #undef FD_ISSET |
Marko Mikulicic |
0:c0ecb8bf28eb | 499 | #undef FD_SET |
Marko Mikulicic |
0:c0ecb8bf28eb | 500 | #undef FD_SETSIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 501 | #undef FD_ZERO |
Marko Mikulicic |
0:c0ecb8bf28eb | 502 | #undef fd_set |
Marko Mikulicic |
0:c0ecb8bf28eb | 503 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 505 | /* We want to disable SL_INC_STD_BSD_API_NAMING, so we include user.h ourselves |
Marko Mikulicic |
0:c0ecb8bf28eb | 506 | * and undef it. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 507 | #define PROVISIONING_API_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 508 | #include <simplelink/user.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 509 | #undef PROVISIONING_API_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 510 | #undef SL_INC_STD_BSD_API_NAMING |
Marko Mikulicic |
0:c0ecb8bf28eb | 511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 512 | #include <simplelink/include/simplelink.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 513 | #include <simplelink/include/netapp.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 514 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 515 | /* Now define only the subset of the BSD API that we use. |
Marko Mikulicic |
0:c0ecb8bf28eb | 516 | * Notably, close(), read() and write() are not defined. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 517 | #define AF_INET SL_AF_INET |
Marko Mikulicic |
0:c0ecb8bf28eb | 518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 519 | #define socklen_t SlSocklen_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 520 | #define sockaddr SlSockAddr_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 521 | #define sockaddr_in SlSockAddrIn_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 522 | #define in_addr SlInAddr_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 523 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 524 | #define SOCK_STREAM SL_SOCK_STREAM |
Marko Mikulicic |
0:c0ecb8bf28eb | 525 | #define SOCK_DGRAM SL_SOCK_DGRAM |
Marko Mikulicic |
0:c0ecb8bf28eb | 526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 527 | #define htonl sl_Htonl |
Marko Mikulicic |
0:c0ecb8bf28eb | 528 | #define ntohl sl_Ntohl |
Marko Mikulicic |
0:c0ecb8bf28eb | 529 | #define htons sl_Htons |
Marko Mikulicic |
0:c0ecb8bf28eb | 530 | #define ntohs sl_Ntohs |
Marko Mikulicic |
0:c0ecb8bf28eb | 531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 532 | #ifndef EACCES |
Marko Mikulicic |
0:c0ecb8bf28eb | 533 | #define EACCES SL_EACCES |
Marko Mikulicic |
0:c0ecb8bf28eb | 534 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 535 | #ifndef EAFNOSUPPORT |
Marko Mikulicic |
0:c0ecb8bf28eb | 536 | #define EAFNOSUPPORT SL_EAFNOSUPPORT |
Marko Mikulicic |
0:c0ecb8bf28eb | 537 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 538 | #ifndef EAGAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 539 | #define EAGAIN SL_EAGAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 540 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 541 | #ifndef EBADF |
Marko Mikulicic |
0:c0ecb8bf28eb | 542 | #define EBADF SL_EBADF |
Marko Mikulicic |
0:c0ecb8bf28eb | 543 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 544 | #ifndef EINVAL |
Marko Mikulicic |
0:c0ecb8bf28eb | 545 | #define EINVAL SL_EINVAL |
Marko Mikulicic |
0:c0ecb8bf28eb | 546 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 547 | #ifndef ENOMEM |
Marko Mikulicic |
0:c0ecb8bf28eb | 548 | #define ENOMEM SL_ENOMEM |
Marko Mikulicic |
0:c0ecb8bf28eb | 549 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 550 | #ifndef EWOULDBLOCK |
Marko Mikulicic |
0:c0ecb8bf28eb | 551 | #define EWOULDBLOCK SL_EWOULDBLOCK |
Marko Mikulicic |
0:c0ecb8bf28eb | 552 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 553 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 554 | #define SOMAXCONN 8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 556 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 557 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 558 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 560 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 561 | char *inet_ntoa(struct in_addr in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 562 | int inet_pton(int af, const char *src, void *dst); |
Marko Mikulicic |
0:c0ecb8bf28eb | 563 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 564 | struct mg_mgr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 565 | struct mg_connection; |
Marko Mikulicic |
0:c0ecb8bf28eb | 566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 567 | typedef void (*mg_init_cb)(struct mg_mgr *mgr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 568 | bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init); |
Marko Mikulicic |
0:c0ecb8bf28eb | 569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 570 | void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 572 | int sl_fs_init(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 574 | void sl_restart_cb(struct mg_mgr *mgr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 576 | int sl_set_ssl_opts(struct mg_connection *nc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 578 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 579 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 580 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 582 | #endif /* defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 584 | #endif /* CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 585 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 586 | #line 1 "common/platforms/platform_cc3200.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 587 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 588 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 589 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 590 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 591 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 593 | #ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 594 | #define CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 595 | #if CS_PLATFORM == CS_P_CC3200 |
Marko Mikulicic |
0:c0ecb8bf28eb | 596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 597 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 598 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 599 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 600 | #include <inttypes.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 601 | #include <stdint.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 602 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 603 | #include <time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 605 | #ifndef __TI_COMPILER_VERSION__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 606 | #include <fcntl.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 607 | #include <sys/time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 608 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 610 | #define MG_SOCKET_SIMPLELINK 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 611 | #define MG_DISABLE_SOCKETPAIR 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 612 | #define MG_DISABLE_SYNC_RESOLVER 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 613 | #define MG_DISABLE_POPEN 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 614 | #define MG_DISABLE_CGI 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 615 | /* Only SPIFFS supports directories, SLFS does not. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 616 | #ifndef CC3200_FS_SPIFFS |
Marko Mikulicic |
0:c0ecb8bf28eb | 617 | #define MG_DISABLE_DAV 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 618 | #define MG_DISABLE_DIRECTORY_LISTING 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 619 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 621 | /* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 623 | typedef int sock_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 624 | #define INVALID_SOCKET (-1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 625 | #define SIZE_T_FMT "u" |
Marko Mikulicic |
0:c0ecb8bf28eb | 626 | typedef struct stat cs_stat_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 627 | #define DIRSEP '/' |
Marko Mikulicic |
0:c0ecb8bf28eb | 628 | #define to64(x) strtoll(x, NULL, 10) |
Marko Mikulicic |
0:c0ecb8bf28eb | 629 | #define INT64_FMT PRId64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 630 | #define INT64_X_FMT PRIx64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 631 | #define __cdecl |
Marko Mikulicic |
0:c0ecb8bf28eb | 632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 633 | #define fileno(x) -1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 634 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 635 | /* Some functions we implement for Mongoose. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 637 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 638 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 639 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 640 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 641 | #ifdef __TI_COMPILER_VERSION__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 642 | struct SlTimeval_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 643 | #define timeval SlTimeval_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 644 | int gettimeofday(struct timeval *t, void *tz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 645 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 646 | int asprintf(char **strp, const char *fmt, ...); |
Marko Mikulicic |
0:c0ecb8bf28eb | 647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 648 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 649 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 650 | /* TI's libc does not have stat & friends, add them. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 651 | #ifdef __TI_COMPILER_VERSION__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 652 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 653 | #include <file.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 655 | typedef unsigned int mode_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 656 | typedef size_t _off_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 657 | typedef long ssize_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 659 | struct stat { |
Marko Mikulicic |
0:c0ecb8bf28eb | 660 | int st_ino; |
Marko Mikulicic |
0:c0ecb8bf28eb | 661 | mode_t st_mode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 662 | int st_nlink; |
Marko Mikulicic |
0:c0ecb8bf28eb | 663 | time_t st_mtime; |
Marko Mikulicic |
0:c0ecb8bf28eb | 664 | off_t st_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 665 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 667 | int _stat(const char *pathname, struct stat *st); |
Marko Mikulicic |
0:c0ecb8bf28eb | 668 | #define stat(a, b) _stat(a, b) |
Marko Mikulicic |
0:c0ecb8bf28eb | 669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 670 | #define __S_IFMT 0170000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 672 | #define __S_IFDIR 0040000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 673 | #define __S_IFCHR 0020000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 674 | #define __S_IFREG 0100000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 675 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 676 | #define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 678 | #define S_IFDIR __S_IFDIR |
Marko Mikulicic |
0:c0ecb8bf28eb | 679 | #define S_IFCHR __S_IFCHR |
Marko Mikulicic |
0:c0ecb8bf28eb | 680 | #define S_IFREG __S_IFREG |
Marko Mikulicic |
0:c0ecb8bf28eb | 681 | #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR) |
Marko Mikulicic |
0:c0ecb8bf28eb | 682 | #define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG) |
Marko Mikulicic |
0:c0ecb8bf28eb | 683 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 684 | /* As of 5.2.7, TI compiler does not support va_copy() yet. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 685 | #define va_copy(apc, ap) ((apc) = (ap)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 687 | #endif /* __TI_COMPILER_VERSION__ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 689 | #ifdef CC3200_FS_SPIFFS |
Marko Mikulicic |
0:c0ecb8bf28eb | 690 | #include <common/spiffs/spiffs.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 692 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 693 | spiffs_DIR dh; |
Marko Mikulicic |
0:c0ecb8bf28eb | 694 | struct spiffs_dirent de; |
Marko Mikulicic |
0:c0ecb8bf28eb | 695 | } DIR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 697 | #define d_name name |
Marko Mikulicic |
0:c0ecb8bf28eb | 698 | #define dirent spiffs_dirent |
Marko Mikulicic |
0:c0ecb8bf28eb | 699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 700 | DIR *opendir(const char *dir_name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 701 | int closedir(DIR *dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 702 | struct dirent *readdir(DIR *dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 703 | #endif /* CC3200_FS_SPIFFS */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 704 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 705 | #ifdef CC3200_FS_SLFS |
Marko Mikulicic |
0:c0ecb8bf28eb | 706 | #define MG_FS_SLFS |
Marko Mikulicic |
0:c0ecb8bf28eb | 707 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 708 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 709 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 710 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 711 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 713 | #endif /* CS_PLATFORM == CS_P_CC3200 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 714 | #endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 715 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 716 | #line 1 "common/platforms/platform_cc3100.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 717 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 718 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 719 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 720 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 721 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 723 | #ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 724 | #define CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 725 | #if CS_PLATFORM == CS_P_CC3100 |
Marko Mikulicic |
0:c0ecb8bf28eb | 726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 727 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 728 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 729 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 730 | #include <inttypes.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 731 | #include <stdint.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 732 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 733 | #include <time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 735 | #define MG_SOCKET_SIMPLELINK 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 736 | #define MG_DISABLE_SOCKETPAIR 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 737 | #define MG_DISABLE_SYNC_RESOLVER 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 738 | #define MG_DISABLE_POPEN 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 739 | #define MG_DISABLE_CGI 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 740 | #define MG_DISABLE_DAV 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 741 | #define MG_DISABLE_DIRECTORY_LISTING 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 742 | #define MG_DISABLE_FILESYSTEM 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 743 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 744 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 745 | * CC3100 SDK and STM32 SDK include headers w/out path, just like |
Marko Mikulicic |
0:c0ecb8bf28eb | 746 | * #include "simplelink.h". As result, we have to add all required directories |
Marko Mikulicic |
0:c0ecb8bf28eb | 747 | * into Makefile IPATH and do the same thing (include w/out path) |
Marko Mikulicic |
0:c0ecb8bf28eb | 748 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 749 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 750 | #include <simplelink.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 751 | #include <netapp.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 752 | #undef timeval |
Marko Mikulicic |
0:c0ecb8bf28eb | 753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 754 | typedef int sock_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 755 | #define INVALID_SOCKET (-1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 756 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 757 | #define to64(x) strtoll(x, NULL, 10) |
Marko Mikulicic |
0:c0ecb8bf28eb | 758 | #define INT64_FMT PRId64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 759 | #define INT64_X_FMT PRIx64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 760 | #define SIZE_T_FMT "u" |
Marko Mikulicic |
0:c0ecb8bf28eb | 761 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 762 | #define SOMAXCONN 8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 764 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 765 | char *inet_ntoa(struct in_addr in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 766 | int inet_pton(int af, const char *src, void *dst); |
Marko Mikulicic |
0:c0ecb8bf28eb | 767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 768 | #endif /* CS_PLATFORM == CS_P_CC3100 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 769 | #endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 770 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
1:887cf63a2a0b | 771 | #line 1 "common/platforms/platform_mbed.h" |
Marko Mikulicic |
1:887cf63a2a0b | 772 | #endif |
Marko Mikulicic |
1:887cf63a2a0b | 773 | /* |
Marko Mikulicic |
1:887cf63a2a0b | 774 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
1:887cf63a2a0b | 775 | * All rights reserved |
Marko Mikulicic |
1:887cf63a2a0b | 776 | */ |
Marko Mikulicic |
1:887cf63a2a0b | 777 | |
Marko Mikulicic |
1:887cf63a2a0b | 778 | #ifndef CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ |
Marko Mikulicic |
1:887cf63a2a0b | 779 | #define CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ |
Marko Mikulicic |
1:887cf63a2a0b | 780 | #if CS_PLATFORM == CS_P_MBED |
Marko Mikulicic |
1:887cf63a2a0b | 781 | |
Marko Mikulicic |
1:887cf63a2a0b | 782 | /* Amalgamated: #include "mbed.h" */ |
Marko Mikulicic |
1:887cf63a2a0b | 783 | |
Marko Mikulicic |
1:887cf63a2a0b | 784 | #endif /* CS_PLATFORM == CS_P_MBED */ |
Marko Mikulicic |
1:887cf63a2a0b | 785 | #endif /* CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ */ |
Marko Mikulicic |
1:887cf63a2a0b | 786 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 787 | #line 1 "common/str_util.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 788 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 789 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 790 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 791 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 792 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 794 | #ifndef CS_COMMON_STR_UTIL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 795 | #define CS_COMMON_STR_UTIL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 797 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 798 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 799 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 800 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 801 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 802 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 804 | size_t c_strnlen(const char *s, size_t maxlen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 805 | int c_snprintf(char *buf, size_t buf_size, const char *format, ...); |
Marko Mikulicic |
0:c0ecb8bf28eb | 806 | int c_vsnprintf(char *buf, size_t buf_size, const char *format, va_list ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 807 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 808 | * Find the first occurrence of find in s, where the search is limited to the |
Marko Mikulicic |
0:c0ecb8bf28eb | 809 | * first slen characters of s. |
Marko Mikulicic |
0:c0ecb8bf28eb | 810 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 811 | const char *c_strnstr(const char *s, const char *find, size_t slen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 813 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 815 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 817 | #endif /* CS_COMMON_STR_UTIL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 818 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 819 | #line 1 "common/utf.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 820 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 821 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 822 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 823 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 824 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 826 | #ifndef CS_COMMON_UTF_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 827 | #define CS_COMMON_UTF_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 829 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 830 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 831 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 832 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 833 | typedef unsigned char uchar; |
Marko Mikulicic |
0:c0ecb8bf28eb | 834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 835 | typedef unsigned short Rune; /* 16 bits */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 836 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 837 | #define nelem(a) (sizeof(a) / sizeof(a)[0]) |
Marko Mikulicic |
0:c0ecb8bf28eb | 838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 839 | enum { |
Marko Mikulicic |
0:c0ecb8bf28eb | 840 | UTFmax = 3, /* maximum bytes per rune */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 841 | Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 842 | Runeself = 0x80, /* rune and UTF sequences are the same (<) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 843 | Runeerror = 0xFFFD /* decoding error in UTF */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 844 | /* Runemax = 0xFFFC */ /* maximum rune value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 845 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 846 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 847 | /* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/utf/?*.c | grep -v static |grep -v __ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 848 | int chartorune(Rune *rune, const char *str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 849 | int fullrune(const char *str, int n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 850 | int isdigitrune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 851 | int isnewline(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 852 | int iswordchar(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 853 | int isalpharune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 854 | int islowerrune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 855 | int isspacerune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 856 | int isupperrune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 857 | int runetochar(char *str, Rune *rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 858 | Rune tolowerrune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 859 | Rune toupperrune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 860 | int utfnlen(const char *s, long m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 861 | const char *utfnshift(const char *s, long m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 863 | #if 0 /* Not implemented. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 864 | int istitlerune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 865 | int runelen(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 866 | int runenlen(Rune *r, int nrune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 867 | Rune *runestrcat(Rune *s1, Rune *s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 868 | Rune *runestrchr(Rune *s, Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 869 | Rune *runestrcpy(Rune *s1, Rune *s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 870 | Rune *runestrdup(Rune *s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 871 | Rune *runestrecpy(Rune *s1, Rune *es1, Rune *s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 872 | int runestrcmp(Rune *s1, Rune *s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 873 | long runestrlen(Rune *s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 874 | Rune *runestrncat(Rune *s1, Rune *s2, long n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 875 | int runestrncmp(Rune *s1, Rune *s2, long n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 876 | Rune *runestrncpy(Rune *s1, Rune *s2, long n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 877 | Rune *runestrrchr(Rune *s, Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 878 | Rune *runestrstr(Rune *s1, Rune *s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 879 | Rune totitlerune(Rune c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 880 | char *utfecpy(char *to, char *e, char *from); |
Marko Mikulicic |
0:c0ecb8bf28eb | 881 | int utflen(char *s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 882 | char *utfrrune(char *s, long c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 883 | char *utfrune(char *s, long c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 884 | char *utfutf(char *s1, char *s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 885 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 887 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 889 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 890 | #endif /* CS_COMMON_UTF_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 891 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 892 | #line 1 "common/base64.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 893 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 894 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 895 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 896 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 897 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 899 | #ifndef CS_COMMON_BASE64_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 900 | #define CS_COMMON_BASE64_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 901 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 902 | #ifndef DISABLE_BASE64 |
Marko Mikulicic |
0:c0ecb8bf28eb | 903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 904 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 906 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 907 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 908 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 910 | typedef void (*cs_base64_putc_t)(char, void *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 912 | struct cs_base64_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 913 | /* cannot call it putc because it's a macro on some environments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 914 | cs_base64_putc_t b64_putc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 915 | unsigned char chunk[3]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 916 | int chunk_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 917 | void *user_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 918 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 920 | void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 921 | void *user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 922 | void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 923 | void cs_base64_finish(struct cs_base64_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 925 | void cs_base64_encode(const unsigned char *src, int src_len, char *dst); |
Marko Mikulicic |
0:c0ecb8bf28eb | 926 | void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 927 | int cs_base64_decode(const unsigned char *s, int len, char *dst); |
Marko Mikulicic |
0:c0ecb8bf28eb | 928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 929 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 930 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 931 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 933 | #endif /* DISABLE_BASE64 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 935 | #endif /* CS_COMMON_BASE64_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 936 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 937 | #line 1 "common/md5.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 938 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 939 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 940 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 941 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 942 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 944 | #ifndef CS_COMMON_MD5_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 945 | #define CS_COMMON_MD5_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 946 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 947 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 948 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 949 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 950 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 951 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 953 | typedef struct MD5Context { |
Marko Mikulicic |
0:c0ecb8bf28eb | 954 | uint32_t buf[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 955 | uint32_t bits[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 956 | unsigned char in[64]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 957 | } MD5_CTX; |
Marko Mikulicic |
0:c0ecb8bf28eb | 958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 959 | void MD5_Init(MD5_CTX *c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 960 | void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 961 | void MD5_Final(unsigned char *md, MD5_CTX *c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 963 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 964 | * Return stringified MD5 hash for NULL terminated list of pointer/length pairs. |
Marko Mikulicic |
0:c0ecb8bf28eb | 965 | * A length should be specified as size_t variable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 966 | * Example: |
Marko Mikulicic |
0:c0ecb8bf28eb | 967 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 968 | * char buf[33]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 969 | * cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 970 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 971 | char *cs_md5(char buf[33], ...); |
Marko Mikulicic |
0:c0ecb8bf28eb | 972 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 973 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 974 | * Stringify binary data. Output buffer size must be 2 * size_of_input + 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 975 | * because each byte of input takes 2 bytes in string representation |
Marko Mikulicic |
0:c0ecb8bf28eb | 976 | * plus 1 byte for the terminating \0 character. |
Marko Mikulicic |
0:c0ecb8bf28eb | 977 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 978 | void cs_to_hex(char *to, const unsigned char *p, size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 980 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 982 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 984 | #endif /* CS_COMMON_MD5_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 985 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 986 | #line 1 "common/sha1.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 987 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 988 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 989 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 990 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 991 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 993 | #ifndef CS_COMMON_SHA1_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 994 | #define CS_COMMON_SHA1_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 996 | #ifndef DISABLE_SHA1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 998 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1000 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 1001 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1002 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1003 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1004 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1005 | uint32_t state[5]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1006 | uint32_t count[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1007 | unsigned char buffer[64]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1008 | } cs_sha1_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1010 | void cs_sha1_init(cs_sha1_ctx *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1011 | void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1012 | void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1013 | void cs_hmac_sha1(const unsigned char *key, size_t key_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1014 | const unsigned char *text, size_t text_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1015 | unsigned char out[20]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1016 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 1017 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 1018 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1020 | #endif /* DISABLE_SHA1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1021 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1022 | #endif /* CS_COMMON_SHA1_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1023 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1024 | #line 1 "common/cs_dirent.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1025 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1026 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1027 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1028 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1029 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1031 | #ifndef CS_COMMON_CS_DIRENT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1032 | #define CS_COMMON_CS_DIRENT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1033 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1034 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 1035 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1036 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1038 | #ifdef CS_ENABLE_SPIFFS |
Marko Mikulicic |
0:c0ecb8bf28eb | 1039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1040 | #include <spiffs.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1042 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1043 | spiffs_DIR dh; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1044 | struct spiffs_dirent de; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1045 | } DIR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1046 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1047 | #define d_name name |
Marko Mikulicic |
0:c0ecb8bf28eb | 1048 | #define dirent spiffs_dirent |
Marko Mikulicic |
0:c0ecb8bf28eb | 1049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1050 | int rmdir(const char *path); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1051 | int mkdir(const char *path, mode_t mode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1053 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1054 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1055 | #if defined(_WIN32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1056 | struct dirent { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1057 | char d_name[MAX_PATH]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1058 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1060 | typedef struct DIR { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1061 | HANDLE handle; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1062 | WIN32_FIND_DATAW info; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1063 | struct dirent result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1064 | } DIR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1065 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1066 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1067 | #if defined(_WIN32) || defined(CS_ENABLE_SPIFFS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1068 | DIR *opendir(const char *dir_name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1069 | int closedir(DIR *dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1070 | struct dirent *readdir(DIR *dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1071 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1073 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 1074 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 1075 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1076 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1077 | #endif /* CS_COMMON_CS_DIRENT_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1078 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1079 | #line 1 "common/cs_file.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1080 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1081 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1082 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1083 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1084 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1085 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1086 | #ifndef CS_COMMON_CS_FILE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1087 | #define CS_COMMON_CS_FILE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1088 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1089 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1091 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 1092 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1093 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1095 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1096 | * Read whole file `path` in memory. It is responsibility of the caller |
Marko Mikulicic |
0:c0ecb8bf28eb | 1097 | * to `free()` allocated memory. File content is guaranteed to be |
Marko Mikulicic |
0:c0ecb8bf28eb | 1098 | * '\0'-terminated. File size is returned in `size` variable, which does not |
Marko Mikulicic |
0:c0ecb8bf28eb | 1099 | * count terminating `\0`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1100 | * Return: allocated memory, or NULL on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1101 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1102 | char *cs_read_file(const char *path, size_t *size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1104 | #ifdef CS_MMAP |
Marko Mikulicic |
0:c0ecb8bf28eb | 1105 | char *cs_mmap_file(const char *path, size_t *size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1106 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1107 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1108 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 1109 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 1110 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1112 | #endif /* CS_COMMON_CS_FILE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1113 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1114 | #line 1 "common/coroutine.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1115 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1116 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1117 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1118 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1119 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1121 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1122 | * Module that provides generic macros and functions to implement "coroutines", |
Marko Mikulicic |
0:c0ecb8bf28eb | 1123 | * i.e. C code that uses `mbuf` as a stack for function calls. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1124 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1125 | * More info: see the design doc: https://goo.gl/kfcG61 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1126 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1128 | #ifndef CS_COMMON_COROUTINE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1129 | #define CS_COMMON_COROUTINE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1131 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1132 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1134 | /* user-defined union, this module only operates on the pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1135 | union user_arg_ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1136 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1137 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1138 | * Type that represents size of local function variables. We assume we'll never |
Marko Mikulicic |
0:c0ecb8bf28eb | 1139 | * need more than 255 bytes of stack frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1140 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1141 | typedef uint8_t cr_locals_size_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1143 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1144 | * Descriptor of a single function; const array of such descriptors should |
Marko Mikulicic |
0:c0ecb8bf28eb | 1145 | * be given to `cr_context_init()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 1146 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1147 | struct cr_func_desc { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1148 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1149 | * Size of the function's data that should be stored on stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1150 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1151 | * NOTE: you should use `CR_LOCALS_SIZEOF(your_type)` instead of `sizeof()`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1152 | * since this value should be aligned by the word boundary, and |
Marko Mikulicic |
0:c0ecb8bf28eb | 1153 | * `CR_LOCALS_SIZEOF()` takes care of this. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1154 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1155 | cr_locals_size_t locals_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1156 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1158 | enum cr_status { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1159 | CR_RES__OK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1160 | CR_RES__OK_YIELDED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1162 | CR_RES__ERR_STACK_OVERFLOW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1164 | /* Underflow can only be caused by memory corruption or bug in CR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1165 | CR_RES__ERR_STACK_DATA_UNDERFLOW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1166 | /* Underflow can only be caused by memory corruption or bug in CR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1167 | CR_RES__ERR_STACK_CALL_UNDERFLOW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1169 | CR_RES__ERR_UNCAUGHT_EXCEPTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1170 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1172 | /* Context of the coroutine engine */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1173 | struct cr_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1174 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1175 | * id of the next "function" to call. If no function is going to be called, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1176 | * it's CR_FID__NONE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1177 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1178 | uint8_t called_fid; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1180 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1181 | * when `called_fid` is not `CR_FID__NONE`, this field holds called |
Marko Mikulicic |
0:c0ecb8bf28eb | 1182 | * function's stack frame size |
Marko Mikulicic |
0:c0ecb8bf28eb | 1183 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1184 | size_t call_locals_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1186 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1187 | * when `called_fid` is not `CR_FID__NONE`, this field holds called |
Marko Mikulicic |
0:c0ecb8bf28eb | 1188 | * function's arguments size |
Marko Mikulicic |
0:c0ecb8bf28eb | 1189 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1190 | size_t call_arg_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1192 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1193 | * pointer to the current function's locals. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1194 | * Needed to make `CR_CUR_LOCALS_PT()` fast. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1195 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1196 | uint8_t *p_cur_func_locals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1198 | /* data stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1199 | struct mbuf stack_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1201 | /* return stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1202 | struct mbuf stack_ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1204 | /* index of the current fid + 1 in return stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1205 | size_t cur_fid_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1207 | /* pointer to the array of function descriptors */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1208 | const struct cr_func_desc *p_func_descrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1210 | /* thrown exception. If nothing is currently thrown, it's `CR_EXC_ID__NONE` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1211 | uint8_t thrown_exc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1213 | /* status: normally, it's `CR_RES__OK` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1214 | enum cr_status status; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1216 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1217 | * pointer to user-dependent union of arguments for all functions, as well as |
Marko Mikulicic |
0:c0ecb8bf28eb | 1218 | * return values, yielded and resumed values. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1219 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1220 | union user_arg_ret *p_arg_retval; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1222 | /* true if currently running function returns */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1223 | unsigned need_return : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1224 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1225 | /* true if currently running function yields */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1226 | unsigned need_yield : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1228 | #if defined(CR_TRACK_MAX_STACK_LEN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1229 | size_t stack_data_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1230 | size_t stack_ret_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1231 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1232 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1233 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1234 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1235 | * User's enum with function ids should use items of this one like this: |
Marko Mikulicic |
0:c0ecb8bf28eb | 1236 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1237 | * enum my_func_id { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1238 | * my_func_none = CR_FID__NONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1239 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1240 | * my_foo = CR_FID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1241 | * my_foo1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1242 | * my_foo2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1243 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1244 | * my_bar, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1245 | * my_bar1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1246 | * }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1247 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1248 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1249 | enum cr_fid { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1250 | CR_FID__NONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1251 | CR_FID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1253 | /* for internal usage only */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1254 | CR_FID__TRY_MARKER = 0xff, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1255 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1257 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1258 | * User's enum with exception ids should use items of this one like this: |
Marko Mikulicic |
0:c0ecb8bf28eb | 1259 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1260 | * enum my_exc_id { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1261 | * MY_EXC_ID__FIRST = CR_EXC_ID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1262 | * MY_EXC_ID__SECOND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1263 | * MY_EXC_ID__THIRD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1264 | * }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1265 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1266 | enum cr_exc_id { |
Marko Mikulicic |
0:c0ecb8bf28eb | 1267 | CR_EXC_ID__NONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1268 | CR_EXC_ID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1269 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1271 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1272 | * A type whose size is a special case for macros `CR_LOCALS_SIZEOF()` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 1273 | * `CR_ARG_SIZEOF()` : it is assumed as zero size. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1274 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1275 | * This hackery is needed because empty structs (that would yield sizeof 0) are |
Marko Mikulicic |
0:c0ecb8bf28eb | 1276 | * illegal in plain C. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1277 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1278 | typedef struct { uint8_t _dummy[((cr_locals_size_t) -1)]; } cr_zero_size_type_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1280 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1281 | * To be used in dispatcher switch: depending on the "fid" (function id), we |
Marko Mikulicic |
0:c0ecb8bf28eb | 1282 | * jump to the appropriate label. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1283 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1284 | #define CR_DEFINE_ENTRY_POINT(fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1285 | case fid: \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1286 | goto fid |
Marko Mikulicic |
0:c0ecb8bf28eb | 1287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1288 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1289 | * Returns lvalue: id of the currently active "function". It just takes the id |
Marko Mikulicic |
0:c0ecb8bf28eb | 1290 | * from the appropriate position of the "stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 1291 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1292 | * Client code only needs it in dispatcher switch. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1293 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1294 | #define CR_CURR_FUNC_C(p_ctx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1295 | *(((cr_locals_size_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->cur_fid_idx - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1297 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1298 | * Prepare context for calling first function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1299 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1300 | * Should be used outside of the exec loop, right after initializing |
Marko Mikulicic |
0:c0ecb8bf28eb | 1301 | * context with `cr_context_init()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 1302 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1303 | * `call_fid`: id of the function to be called |
Marko Mikulicic |
0:c0ecb8bf28eb | 1304 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1305 | #define CR_FIRST_CALL_PREPARE_C(p_ctx, call_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1306 | _CR_CALL_PREPARE(p_ctx, call_fid, CR_LOCALS_SIZEOF(call_fid##_locals_t), \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1307 | CR_ARG_SIZEOF(call_fid##_arg_t), CR_FID__NONE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1309 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1310 | * Call "function" with id `call_fid`: uses `_CR_CALL_PREPARE()` to prepare |
Marko Mikulicic |
0:c0ecb8bf28eb | 1311 | * stuff, and then jumps to the `_cr_iter_begin`, which will perform all |
Marko Mikulicic |
0:c0ecb8bf28eb | 1312 | * necessary bookkeeping. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1313 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1314 | * Should be used from eval loop only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1315 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1316 | * `local_ret_fid`: id of the label right after the function call (where |
Marko Mikulicic |
0:c0ecb8bf28eb | 1317 | * currently running function will be resumed later) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1318 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1319 | #define CR_CALL_C(p_ctx, call_fid, local_ret_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1320 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1321 | _CR_CALL_PREPARE(p_ctx, call_fid, CR_LOCALS_SIZEOF(call_fid##_locals_t), \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1322 | CR_ARG_SIZEOF(call_fid##_arg_t), local_ret_fid); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1323 | goto _cr_iter_begin; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1324 | local_ret_fid: \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1325 | /* we'll get here when called function returns */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1326 | ; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1327 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1328 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1329 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1330 | * "Return" the value `retval` from the current "function" with id `cur_fid`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1331 | * You have to specify `cur_fid` since different functions may have different |
Marko Mikulicic |
0:c0ecb8bf28eb | 1332 | * return types. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1333 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1334 | * Should be used from eval loop only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1335 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1336 | #define CR_RETURN_C(p_ctx, cur_fid, retval) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1337 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1338 | /* copy ret to arg_retval */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1339 | CR_ARG_RET_PT_C(p_ctx)->ret.cur_fid = (retval); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1340 | /* set need_return flag */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1341 | (p_ctx)->need_return = 1; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1342 | goto _cr_iter_begin; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1343 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1345 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1346 | * Same as `CR_RETURN_C`, but without any return value |
Marko Mikulicic |
0:c0ecb8bf28eb | 1347 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1348 | #define CR_RETURN_VOID_C(p_ctx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1349 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1350 | /* set need_return flag */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1351 | (p_ctx)->need_return = 1; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1352 | goto _cr_iter_begin; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1353 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1355 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1356 | * Yield with the value `value`. It will be set just by the assigment operator |
Marko Mikulicic |
0:c0ecb8bf28eb | 1357 | * in the `yielded` field of the `union user_arg_ret`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1358 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1359 | * `local_ret_fid`: id of the label right after the yielding (where currently |
Marko Mikulicic |
0:c0ecb8bf28eb | 1360 | * running function will be resumed later) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1361 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1362 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1363 | #define CR_YIELD_C(p_ctx, value, local_ret_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1364 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1365 | /* copy ret to arg_retval */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1366 | CR_ARG_RET_PT_C(p_ctx)->yielded = (value); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1367 | /* set need_yield flag */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1368 | (p_ctx)->need_yield = 1; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1369 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1370 | /* adjust return func id */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1371 | CR_CURR_FUNC_C(p_ctx) = (local_ret_fid); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1372 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1373 | goto _cr_iter_begin; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1374 | local_ret_fid: \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1375 | /* we'll get here when the machine will be resumed */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1376 | ; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1377 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1379 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1380 | * Prepare context for resuming with the given value. After using this |
Marko Mikulicic |
0:c0ecb8bf28eb | 1381 | * macro, you need to call your user-dependent exec function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1382 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1383 | #define CR_RESUME_C(p_ctx, value) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1384 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1385 | if ((p_ctx)->status == CR_RES__OK_YIELDED) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1386 | CR_ARG_RET_PT_C(p_ctx)->resumed = (value); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1387 | (p_ctx)->status = CR_RES__OK; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1388 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1389 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1391 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1392 | * Evaluates to the yielded value (value given to `CR_YIELD_C()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1393 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1394 | #define CR_YIELDED_C(p_ctx) (CR_ARG_RET_PT_C(p_ctx)->yielded) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1396 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1397 | * Evaluates to the value given to `CR_RESUME_C()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 1398 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1399 | #define CR_RESUMED_C(p_ctx) (CR_ARG_RET_PT_C(p_ctx)->resumed) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1400 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1401 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1402 | * Beginning of the try-catch block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1403 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1404 | * Should be used in eval loop only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1405 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1406 | * `first_catch_fid`: function id of the first catch block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1407 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1408 | #define CR_TRY_C(p_ctx, first_catch_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1409 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1410 | _CR_STACK_RET_ALLOC((p_ctx), _CR_TRY_SIZE); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1411 | /* update pointer to current function's locals (may be invalidated) */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1412 | _CR_CUR_FUNC_LOCALS_UPD(p_ctx); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1413 | /* */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1414 | _CR_TRY_MARKER(p_ctx) = CR_FID__TRY_MARKER; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1415 | _CR_TRY_CATCH_FID(p_ctx) = (first_catch_fid); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1416 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1417 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1418 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1419 | * Beginning of the individual catch block (and the end of the previous one, if |
Marko Mikulicic |
0:c0ecb8bf28eb | 1420 | * any) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1421 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1422 | * Should be used in eval loop only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1423 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1424 | * `exc_id`: exception id to catch |
Marko Mikulicic |
0:c0ecb8bf28eb | 1425 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1426 | * `catch_fid`: function id of this catch block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1427 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1428 | * `next_catch_fid`: function id of the next catch block (or of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 1429 | * `CR_ENDCATCH()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1430 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1431 | #define CR_CATCH_C(p_ctx, exc_id, catch_fid, next_catch_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1432 | catch_fid: \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1433 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1434 | if ((p_ctx)->thrown_exc != (exc_id)) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1435 | goto next_catch_fid; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1436 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1437 | (p_ctx)->thrown_exc = CR_EXC_ID__NONE; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1438 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1440 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1441 | * End of all catch blocks. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1442 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1443 | * Should be used in eval loop only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1444 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1445 | * `endcatch_fid`: function id of this endcatch. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1446 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1447 | #define CR_ENDCATCH_C(p_ctx, endcatch_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1448 | endcatch_fid: \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1449 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1450 | (p_ctx)->stack_ret.len -= _CR_TRY_SIZE; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1451 | /* if we still have non-handled exception, continue unwinding "stack" */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1452 | if ((p_ctx)->thrown_exc != CR_EXC_ID__NONE) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1453 | goto _cr_iter_begin; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1454 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1455 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1457 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1458 | * Throw exception. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1459 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1460 | * Should be used from eval loop only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1461 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1462 | * `exc_id`: exception id to throw |
Marko Mikulicic |
0:c0ecb8bf28eb | 1463 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1464 | #define CR_THROW_C(p_ctx, exc_id) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1465 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1466 | assert((enum cr_exc_id)(exc_id) != CR_EXC_ID__NONE); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1467 | /* clear need_return flag */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1468 | (p_ctx)->thrown_exc = (exc_id); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1469 | goto _cr_iter_begin; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1470 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1472 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1473 | * Get latest returned value from the given "function". |
Marko Mikulicic |
0:c0ecb8bf28eb | 1474 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1475 | * `fid`: id of the function which returned value. Needed to ret value value |
Marko Mikulicic |
0:c0ecb8bf28eb | 1476 | * from the right field in the `(p_ctx)->arg_retval.ret` (different functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 1477 | * may have different return types) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1478 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1479 | #define CR_RETURNED_C(p_ctx, fid) (CR_ARG_RET_PT_C(p_ctx)->ret.fid) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1481 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1482 | * Get currently thrown exception id. If nothing is being thrown at the moment, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1483 | * `CR_EXC_ID__NONE` is returned |
Marko Mikulicic |
0:c0ecb8bf28eb | 1484 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1485 | #define CR_THROWN_C(p_ctx) ((p_ctx)->thrown_exc) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1486 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1487 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1488 | * Like `sizeof()`, but it always evaluates to the multiple of `sizeof(void *)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 1489 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1490 | * It should be used for (struct cr_func_desc)::locals_size |
Marko Mikulicic |
0:c0ecb8bf28eb | 1491 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1492 | * NOTE: instead of checking `sizeof(type) <= ((cr_locals_size_t) -1)`, I'd |
Marko Mikulicic |
0:c0ecb8bf28eb | 1493 | * better put the calculated value as it is, and if it overflows, then compiler |
Marko Mikulicic |
0:c0ecb8bf28eb | 1494 | * will generate warning, and this would help us to reveal our mistake. But |
Marko Mikulicic |
0:c0ecb8bf28eb | 1495 | * unfortunately, clang *always* generates this warning (even if the whole |
Marko Mikulicic |
0:c0ecb8bf28eb | 1496 | * expression yields 0), so we have to apply a bit more of dirty hacks here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1497 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1498 | #define CR_LOCALS_SIZEOF(type) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1499 | ((sizeof(type) == sizeof(cr_zero_size_type_t)) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1500 | ? 0 \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1501 | : (sizeof(type) <= ((cr_locals_size_t) -1) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1502 | ? ((cr_locals_size_t)(((sizeof(type)) + (sizeof(void *) - 1)) & \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1503 | (~(sizeof(void *) - 1)))) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1504 | : ((cr_locals_size_t) -1))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1506 | #define CR_ARG_SIZEOF(type) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1507 | ((sizeof(type) == sizeof(cr_zero_size_type_t)) ? 0 : sizeof(type)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1509 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1510 | * Returns pointer to the current function's stack locals, and casts to given |
Marko Mikulicic |
0:c0ecb8bf28eb | 1511 | * type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1512 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1513 | * Typical usage might look as follows: |
Marko Mikulicic |
0:c0ecb8bf28eb | 1514 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1515 | * #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 1516 | * #define L CR_CUR_LOCALS_PT(p_ctx, struct my_foo_locals) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1517 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1518 | * Then, assuming `struct my_foo_locals` has the field `bar`, we can access it |
Marko Mikulicic |
0:c0ecb8bf28eb | 1519 | * like this: |
Marko Mikulicic |
0:c0ecb8bf28eb | 1520 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1521 | * L->bar |
Marko Mikulicic |
0:c0ecb8bf28eb | 1522 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1523 | #define CR_CUR_LOCALS_PT_C(p_ctx, type) ((type *) ((p_ctx)->p_cur_func_locals)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1525 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1526 | * Returns pointer to the user-defined union of arguments and return values: |
Marko Mikulicic |
0:c0ecb8bf28eb | 1527 | * `union user_arg_ret` |
Marko Mikulicic |
0:c0ecb8bf28eb | 1528 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1529 | #define CR_ARG_RET_PT_C(p_ctx) ((p_ctx)->p_arg_retval) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1531 | #define CR_ARG_RET_PT() CR_ARG_RET_PT_C(p_ctx) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1533 | #define CR_CUR_LOCALS_PT(type) CR_CUR_LOCALS_PT_C(p_ctx, type) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1535 | #define CR_CURR_FUNC() CR_CURR_FUNC_C(p_ctx) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1537 | #define CR_CALL(call_fid, local_ret_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1538 | CR_CALL_C(p_ctx, call_fid, local_ret_fid) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1540 | #define CR_RETURN(cur_fid, retval) CR_RETURN_C(p_ctx, cur_fid, retval) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1542 | #define CR_RETURN_VOID() CR_RETURN_VOID_C(p_ctx) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1544 | #define CR_RETURNED(fid) CR_RETURNED_C(p_ctx, fid) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1546 | #define CR_YIELD(value, local_ret_fid) CR_YIELD_C(p_ctx, value, local_ret_fid) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1548 | #define CR_YIELDED() CR_YIELDED_C(p_ctx) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1549 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1550 | #define CR_RESUME(value) CR_RESUME_C(p_ctx, value) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1552 | #define CR_RESUMED() CR_RESUMED_C(p_ctx) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1553 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1554 | #define CR_TRY(catch_name) CR_TRY_C(p_ctx, catch_name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1556 | #define CR_CATCH(exc_id, catch_name, next_catch_name) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1557 | CR_CATCH_C(p_ctx, exc_id, catch_name, next_catch_name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1558 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1559 | #define CR_ENDCATCH(endcatch_name) CR_ENDCATCH_C(p_ctx, endcatch_name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1561 | #define CR_THROW(exc_id) CR_THROW_C(p_ctx, exc_id) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1563 | /* Private macros {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1565 | #define _CR_CUR_FUNC_LOCALS_UPD(p_ctx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1566 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1567 | (p_ctx)->p_cur_func_locals = (uint8_t *) (p_ctx)->stack_data.buf + \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1568 | (p_ctx)->stack_data.len - \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1569 | _CR_CURR_FUNC_LOCALS_SIZE(p_ctx); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1570 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1572 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1573 | * Size of the stack needed for each try-catch block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1574 | * Use `_CR_TRY_MARKER()` and `_CR_TRY_CATCH_FID()` to get/set parts. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1575 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1576 | #define _CR_TRY_SIZE 2 /*CR_FID__TRY_MARKER, catch_fid*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1578 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1579 | * Evaluates to lvalue where `CR_FID__TRY_MARKER` should be stored |
Marko Mikulicic |
0:c0ecb8bf28eb | 1580 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1581 | #define _CR_TRY_MARKER(p_ctx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1582 | *(((uint8_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->stack_ret.len - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1584 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1585 | * Evaluates to lvalue where `catch_fid` should be stored |
Marko Mikulicic |
0:c0ecb8bf28eb | 1586 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1587 | #define _CR_TRY_CATCH_FID(p_ctx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1588 | *(((uint8_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->stack_ret.len - 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1589 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1590 | #define _CR_CURR_FUNC_LOCALS_SIZE(p_ctx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1591 | ((p_ctx)->p_func_descrs[CR_CURR_FUNC_C(p_ctx)].locals_size) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1593 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1594 | * Prepare context for calling next function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1595 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1596 | * See comments for `CR_CALL()` macro. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1597 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1598 | #define _CR_CALL_PREPARE(p_ctx, _call_fid, _locals_size, _arg_size, \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1599 | local_ret_fid) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1600 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1601 | /* adjust return func id */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1602 | CR_CURR_FUNC_C(p_ctx) = (local_ret_fid); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1603 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1604 | /* set called_fid */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1605 | (p_ctx)->called_fid = (_call_fid); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1606 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1607 | /* set sizes: locals and arg */ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1608 | (p_ctx)->call_locals_size = (_locals_size); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1609 | (p_ctx)->call_arg_size = (_arg_size); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1610 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1612 | #define _CR_STACK_DATA_OVF_CHECK(p_ctx, inc) (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1614 | #define _CR_STACK_DATA_UND_CHECK(p_ctx, dec) ((p_ctx)->stack_data.len < (dec)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1616 | #define _CR_STACK_RET_OVF_CHECK(p_ctx, inc) (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1618 | #define _CR_STACK_RET_UND_CHECK(p_ctx, dec) ((p_ctx)->stack_ret.len < (dec)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1620 | #define _CR_STACK_FID_OVF_CHECK(p_ctx, inc) (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1621 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1622 | #define _CR_STACK_FID_UND_CHECK(p_ctx, dec) ((p_ctx)->cur_fid_idx < (dec)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1624 | #if defined(CR_TRACK_MAX_STACK_LEN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1626 | #define _CR_STACK_DATA_ALLOC(p_ctx, inc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1627 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1628 | mbuf_append(&((p_ctx)->stack_data), NULL, (inc)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1629 | if ((p_ctx)->stack_data_max_len < (p_ctx)->stack_data.len) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1630 | (p_ctx)->stack_data_max_len = (p_ctx)->stack_data.len; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1631 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1632 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1634 | #define _CR_STACK_RET_ALLOC(p_ctx, inc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1635 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1636 | mbuf_append(&((p_ctx)->stack_ret), NULL, (inc)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1637 | if ((p_ctx)->stack_ret_max_len < (p_ctx)->stack_ret.len) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1638 | (p_ctx)->stack_ret_max_len = (p_ctx)->stack_ret.len; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1639 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1640 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1641 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1642 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 1643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1644 | #define _CR_STACK_DATA_ALLOC(p_ctx, inc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1645 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1646 | mbuf_append(&((p_ctx)->stack_data), NULL, (inc)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1647 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1649 | #define _CR_STACK_RET_ALLOC(p_ctx, inc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1650 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1651 | mbuf_append(&((p_ctx)->stack_ret), NULL, (inc)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1652 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1654 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1656 | #define _CR_STACK_DATA_FREE(p_ctx, dec) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1657 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1658 | (p_ctx)->stack_data.len -= (dec); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1659 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1661 | #define _CR_STACK_RET_FREE(p_ctx, dec) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1662 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1663 | (p_ctx)->stack_ret.len -= (dec); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1664 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1666 | #define _CR_STACK_FID_ALLOC(p_ctx, inc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1667 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1668 | (p_ctx)->cur_fid_idx += (inc); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1669 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1671 | #define _CR_STACK_FID_FREE(p_ctx, dec) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1672 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1673 | (p_ctx)->cur_fid_idx -= (dec); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1674 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1675 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1676 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1678 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1679 | * Should be used in eval loop right after `_cr_iter_begin:` label |
Marko Mikulicic |
0:c0ecb8bf28eb | 1680 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1681 | enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1683 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1684 | * Initialize context `p_ctx`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1685 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1686 | * `p_arg_retval`: pointer to the user-defined `union user_arg_ret` |
Marko Mikulicic |
0:c0ecb8bf28eb | 1687 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 1688 | * `p_func_descrs`: array of all user function descriptors |
Marko Mikulicic |
0:c0ecb8bf28eb | 1689 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1690 | void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1691 | size_t arg_retval_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 1692 | const struct cr_func_desc *p_func_descrs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1694 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1695 | * free resources occupied by context (at least, "stack" arrays) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1696 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1697 | void cr_context_free(struct cr_ctx *p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 1698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1699 | #endif /* CS_COMMON_COROUTINE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1700 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1701 | #line 1 "v7/src/features_profiles.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1702 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1703 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1704 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1705 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1706 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1708 | #ifndef CS_V7_SRC_FEATURES_PROFILES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1709 | #define CS_V7_SRC_FEATURES_PROFILES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1711 | #define V7_BUILD_PROFILE_MINIMAL 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1712 | #define V7_BUILD_PROFILE_MEDIUM 2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1713 | #define V7_BUILD_PROFILE_FULL 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1714 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1715 | #ifndef V7_BUILD_PROFILE |
Marko Mikulicic |
0:c0ecb8bf28eb | 1716 | #define V7_BUILD_PROFILE V7_BUILD_PROFILE_FULL |
Marko Mikulicic |
0:c0ecb8bf28eb | 1717 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1719 | #endif /* CS_V7_SRC_FEATURES_PROFILES_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1720 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1721 | #line 1 "v7/src/features_minimal.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1722 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1723 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1724 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1725 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1726 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1727 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1728 | /* Amalgamated: #include "v7/src/features_profiles.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1730 | #if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MINIMAL |
Marko Mikulicic |
0:c0ecb8bf28eb | 1731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1732 | /* This space is intentionally left blank. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1733 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1734 | #endif /* CS_V7_SRC_FEATURES_MINIMAL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1735 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1736 | #line 1 "v7/src/features_medium.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1737 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1738 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1739 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1740 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1741 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1743 | /* Amalgamated: #include "v7/src/features_profiles.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1745 | #if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MEDIUM |
Marko Mikulicic |
0:c0ecb8bf28eb | 1746 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1747 | #define V7_ENABLE__Date 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1748 | #define V7_ENABLE__Date__now 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1749 | #define V7_ENABLE__Date__UTC 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1750 | #define V7_ENABLE__Math 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1751 | #define V7_ENABLE__Math__atan2 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1752 | #define V7_ENABLE__RegExp 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1754 | #endif /* CS_V7_SRC_FEATURES_MEDIUM_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1755 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1756 | #line 1 "v7/src/features_full.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1757 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1758 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1759 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1760 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1761 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1762 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1763 | #ifndef CS_V7_SRC_FEATURES_FULL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1764 | #define CS_V7_SRC_FEATURES_FULL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1765 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1766 | /* Amalgamated: #include "v7/src/features_profiles.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1768 | #if V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL |
Marko Mikulicic |
0:c0ecb8bf28eb | 1769 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1770 | * DO NOT EDIT. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1771 | * This file is generated by scripts/gen-features-full.pl. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1772 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1773 | #ifndef CS_ENABLE_UTF8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1774 | #define CS_ENABLE_UTF8 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1775 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1777 | #define V7_ENABLE__Array__reduce 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1778 | #define V7_ENABLE__Blob 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1779 | #define V7_ENABLE__Date 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1780 | #define V7_ENABLE__Date__UTC 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1781 | #define V7_ENABLE__Date__getters 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1782 | #define V7_ENABLE__Date__now 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1783 | #define V7_ENABLE__Date__parse 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1784 | #define V7_ENABLE__Date__setters 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1785 | #define V7_ENABLE__Date__toJSON 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1786 | #define V7_ENABLE__Date__toLocaleString 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1787 | #define V7_ENABLE__Date__toString 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1788 | #define V7_ENABLE__File__list 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1789 | #define V7_ENABLE__File__require 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1790 | #define V7_ENABLE__Function__bind 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1791 | #define V7_ENABLE__Function__call 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1792 | #define V7_ENABLE__Math 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1793 | #define V7_ENABLE__Math__abs 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1794 | #define V7_ENABLE__Math__acos 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1795 | #define V7_ENABLE__Math__asin 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1796 | #define V7_ENABLE__Math__atan 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1797 | #define V7_ENABLE__Math__atan2 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1798 | #define V7_ENABLE__Math__ceil 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1799 | #define V7_ENABLE__Math__constants 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1800 | #define V7_ENABLE__Math__cos 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1801 | #define V7_ENABLE__Math__exp 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1802 | #define V7_ENABLE__Math__floor 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1803 | #define V7_ENABLE__Math__log 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1804 | #define V7_ENABLE__Math__max 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1805 | #define V7_ENABLE__Math__min 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1806 | #define V7_ENABLE__Math__pow 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1807 | #define V7_ENABLE__Math__random 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1808 | #define V7_ENABLE__Math__round 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1809 | #define V7_ENABLE__Math__sin 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1810 | #define V7_ENABLE__Math__sqrt 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1811 | #define V7_ENABLE__Math__tan 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1812 | #define V7_ENABLE__Memory__stats 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1813 | #define V7_ENABLE__NUMBER__NEGATIVE_INFINITY 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1814 | #define V7_ENABLE__NUMBER__POSITIVE_INFINITY 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1815 | #define V7_ENABLE__Object__create 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1816 | #define V7_ENABLE__Object__defineProperties 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1817 | #define V7_ENABLE__Object__getOwnPropertyDescriptor 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1818 | #define V7_ENABLE__Object__getOwnPropertyNames 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1819 | #define V7_ENABLE__Object__getPrototypeOf 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1820 | #define V7_ENABLE__Object__hasOwnProperty 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1821 | #define V7_ENABLE__Object__isExtensible 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1822 | #define V7_ENABLE__Object__isFrozen 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1823 | #define V7_ENABLE__Object__isPrototypeOf 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1824 | #define V7_ENABLE__Object__isSealed 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1825 | #define V7_ENABLE__Object__keys 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1826 | #define V7_ENABLE__Object__preventExtensions 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1827 | #define V7_ENABLE__Object__propertyIsEnumerable 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1828 | #define V7_ENABLE__Proxy 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1829 | #define V7_ENABLE__RegExp 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1830 | #define V7_ENABLE__StackTrace 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1831 | #define V7_ENABLE__String__localeCompare 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1832 | #define V7_ENABLE__String__localeLowerCase 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1833 | #define V7_ENABLE__String__localeUpperCase 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1835 | #endif /* V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1836 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1837 | #endif /* CS_V7_SRC_FEATURES_FULL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1838 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1839 | #line 1 "v7/src/v7_features.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1840 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1841 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1842 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1843 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1844 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1846 | #ifndef CS_V7_SRC_V7_FEATURES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1847 | #define CS_V7_SRC_V7_FEATURES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1849 | /* Only one will actually be used based on V7_BUILD_PROFILE. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1850 | /* Amalgamated: #include "v7/src/features_minimal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1851 | /* Amalgamated: #include "v7/src/features_medium.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1852 | /* Amalgamated: #include "v7/src/features_full.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1854 | #endif /* CS_V7_SRC_V7_FEATURES_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1855 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1856 | #line 1 "v7/src/internal.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1857 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1858 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1859 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1860 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1861 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1863 | #ifndef CS_V7_SRC_INTERNAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1864 | #define CS_V7_SRC_INTERNAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1866 | /* Amalgamated: #include "v7/src/license.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1868 | /* Check whether we're compiling in an environment with no filesystem */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1869 | #if defined(ARDUINO) && (ARDUINO == 106) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1870 | #define V7_NO_FS |
Marko Mikulicic |
0:c0ecb8bf28eb | 1871 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1873 | #ifndef FAST |
Marko Mikulicic |
0:c0ecb8bf28eb | 1874 | #define FAST |
Marko Mikulicic |
0:c0ecb8bf28eb | 1875 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1876 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1877 | #ifndef STATIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 1878 | #define STATIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 1879 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1880 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1881 | #ifndef ENDL |
Marko Mikulicic |
0:c0ecb8bf28eb | 1882 | #define ENDL "\n" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1883 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1885 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1886 | * In some compilers (watcom) NAN == NAN (and other comparisons) don't follow |
Marko Mikulicic |
0:c0ecb8bf28eb | 1887 | * the rules of IEEE 754. Since we don't know a priori which compilers |
Marko Mikulicic |
0:c0ecb8bf28eb | 1888 | * will generate correct code, we disable the fallback on selected platforms. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1889 | * TODO(mkm): selectively disable on clang/gcc once we test this out. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1890 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1891 | #define V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 1892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1893 | #undef _POSIX_C_SOURCE |
Marko Mikulicic |
0:c0ecb8bf28eb | 1894 | #define _POSIX_C_SOURCE 200809L |
Marko Mikulicic |
0:c0ecb8bf28eb | 1895 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1896 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1897 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 1898 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1899 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1900 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1901 | #include <float.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1902 | #include <limits.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1903 | #include <math.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1904 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1905 | #include <stddef.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1906 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1907 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1908 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1909 | #include <setjmp.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1911 | /* Public API. Implemented in api.c */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1912 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1913 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1914 | #ifdef V7_WINDOWS |
Marko Mikulicic |
0:c0ecb8bf28eb | 1915 | #define vsnprintf _vsnprintf |
Marko Mikulicic |
0:c0ecb8bf28eb | 1916 | #define snprintf _snprintf |
Marko Mikulicic |
0:c0ecb8bf28eb | 1917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1918 | /* VS2015 Update 1 has ISO C99 `isnan` and `isinf` defined in math.h */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1919 | #if _MSC_FULL_VER < 190023506 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1920 | #define isnan(x) _isnan(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1921 | #define isinf(x) (!_finite(x)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1922 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1924 | #define __unused __pragma(warning(suppress : 4100)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1925 | typedef __int64 int64_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1926 | typedef int int32_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1927 | typedef unsigned int uint32_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1928 | typedef unsigned short uint16_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1929 | typedef unsigned char uint8_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1931 | /* For 64bit VisualStudio 2010 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1932 | #ifndef _UINTPTR_T_DEFINED |
Marko Mikulicic |
0:c0ecb8bf28eb | 1933 | typedef unsigned long uintptr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1934 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1936 | #ifndef __func__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1937 | #define __func__ "" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1938 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1940 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 1941 | #include <stdint.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1942 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1944 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1946 | /* MSVC6 doesn't have standard C math constants defined */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1947 | #ifndef M_E |
Marko Mikulicic |
0:c0ecb8bf28eb | 1948 | #define M_E 2.71828182845904523536028747135266250 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1949 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1950 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1951 | #ifndef M_LOG2E |
Marko Mikulicic |
0:c0ecb8bf28eb | 1952 | #define M_LOG2E 1.44269504088896340735992468100189214 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1953 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1955 | #ifndef M_LOG10E |
Marko Mikulicic |
0:c0ecb8bf28eb | 1956 | #define M_LOG10E 0.434294481903251827651128918916605082 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1957 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1959 | #ifndef M_LN2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1960 | #define M_LN2 0.693147180559945309417232121458176568 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1961 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1963 | #ifndef M_LN10 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1964 | #define M_LN10 2.30258509299404568401799145468436421 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1965 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1967 | #ifndef M_PI |
Marko Mikulicic |
0:c0ecb8bf28eb | 1968 | #define M_PI 3.14159265358979323846264338327950288 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1969 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1971 | #ifndef M_SQRT2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1972 | #define M_SQRT2 1.41421356237309504880168872420969808 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1973 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1975 | #ifndef M_SQRT1_2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1976 | #define M_SQRT1_2 0.707106781186547524400844362104849039 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1977 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1979 | #ifndef NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 1980 | extern double _v7_nan; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1981 | #define HAS_V7_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 1982 | #define NAN (_v7_nan) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1983 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1984 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1985 | #ifndef INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 1986 | extern double _v7_infinity; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1987 | #define HAS_V7_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 1988 | #define INFINITY (_v7_infinity) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1989 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1991 | #ifndef EXIT_SUCCESS |
Marko Mikulicic |
0:c0ecb8bf28eb | 1992 | #define EXIT_SUCCESS 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1993 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1995 | #ifndef EXIT_FAILURE |
Marko Mikulicic |
0:c0ecb8bf28eb | 1996 | #define EXIT_FAILURE 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1997 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1999 | #if defined(V7_ENABLE_GC_CHECK) || defined(V7_STACK_GUARD_MIN_SIZE) || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2000 | defined(V7_ENABLE_STACK_TRACKING) || defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2001 | /* Need to enable GCC/clang instrumentation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2002 | #define V7_CYG_PROFILE_ON |
Marko Mikulicic |
0:c0ecb8bf28eb | 2003 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2005 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2006 | extern struct v7 *v7_head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2008 | #if defined(V7_STACK_GUARD_MIN_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2009 | extern void *v7_sp_limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2010 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2011 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2013 | #ifndef ARRAY_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2014 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2015 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2017 | #define V7_STATIC_ASSERT(COND, MSG) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2018 | typedef char static_assertion_##MSG[2 * (!!(COND)) - 1] |
Marko Mikulicic |
0:c0ecb8bf28eb | 2019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2020 | #define BUF_LEFT(size, used) (((size_t)(used) < (size)) ? ((size) - (used)) : 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2021 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2022 | #endif /* CS_V7_SRC_INTERNAL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2023 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2024 | #line 1 "v7/src/core_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2025 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2026 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2027 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2028 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2029 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2031 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2032 | * === Core |
Marko Mikulicic |
0:c0ecb8bf28eb | 2033 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2035 | #ifndef CS_V7_SRC_CORE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2036 | #define CS_V7_SRC_CORE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2038 | #ifndef _POSIX_C_SOURCE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2039 | #define _POSIX_C_SOURCE 200809L |
Marko Mikulicic |
0:c0ecb8bf28eb | 2040 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2042 | /* Amalgamated: #include "v7/src/license.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2043 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2045 | #include <stddef.h> /* For size_t */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2046 | #include <stdio.h> /* For FILE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2047 | |
Marko Mikulicic |
2:7762b98d31c7 | 2048 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 2049 | extern "C" { |
Marko Mikulicic |
2:7762b98d31c7 | 2050 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 2051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2052 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2053 | * TODO(dfrank) : improve amalgamation, so that we'll be able to include |
Marko Mikulicic |
0:c0ecb8bf28eb | 2054 | * files here, and include common/platform.h |
Marko Mikulicic |
0:c0ecb8bf28eb | 2055 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2056 | * For now, copy-pasting `WARN_UNUSED_RESULT` here |
Marko Mikulicic |
0:c0ecb8bf28eb | 2057 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2058 | #ifdef __GNUC__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2059 | #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2060 | #define NOINSTR __attribute__((no_instrument_function)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2061 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 2062 | #define WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2063 | #define NOINSTR |
Marko Mikulicic |
0:c0ecb8bf28eb | 2064 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2066 | #define V7_VERSION "1.0" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2067 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2068 | #if (defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)) || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2069 | (defined(_MSC_VER) && _MSC_VER <= 1200) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2070 | #define V7_WINDOWS |
Marko Mikulicic |
0:c0ecb8bf28eb | 2071 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2073 | #ifdef V7_WINDOWS |
Marko Mikulicic |
0:c0ecb8bf28eb | 2074 | typedef unsigned __int64 uint64_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2075 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 2076 | #include <inttypes.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 2077 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2078 | /* 64-bit value, used to store JS values */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2079 | typedef uint64_t v7_val_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2080 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2081 | /* JavaScript `null` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2082 | #define V7_NULL ((uint64_t) 0xfffe << 48) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2084 | /* JavaScript `undefined` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2085 | #define V7_UNDEFINED ((uint64_t) 0xfffd << 48) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2086 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2087 | /* This if-0 is a dirty workaround to force etags to pick `struct v7` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2088 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2089 | /* Opaque structure. V7 engine context. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2090 | struct v7 { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2091 | /* ... */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2092 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2093 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2095 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2097 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2098 | * Code which is returned by some of the v7 functions. If something other than |
Marko Mikulicic |
0:c0ecb8bf28eb | 2099 | * `V7_OK` is returned from some function, the caller function typically should |
Marko Mikulicic |
0:c0ecb8bf28eb | 2100 | * either immediately cleanup and return the code further, or handle the error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2101 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2102 | enum v7_err { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2103 | V7_OK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2104 | V7_SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2105 | V7_EXEC_EXCEPTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2106 | V7_AST_TOO_LARGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2107 | V7_INTERNAL_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2108 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2110 | /* JavaScript -> C call interface */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2111 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2112 | typedef enum v7_err(v7_cfunction_t)(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2113 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2114 | /* Create V7 instance */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2115 | struct v7 *v7_create(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2116 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2117 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2118 | * Customizations of initial V7 state; used by `v7_create_opt()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2119 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2120 | struct v7_create_opts { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2121 | size_t object_arena_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2122 | size_t function_arena_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2123 | size_t property_arena_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2124 | #ifdef V7_STACK_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2125 | void *c_stack_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2126 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2127 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2128 | /* if not NULL, dump JS heap after init */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2129 | char *freeze_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2130 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2131 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2132 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2133 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2134 | * Like `v7_create()`, but allows to customize initial v7 state, see `struct |
Marko Mikulicic |
0:c0ecb8bf28eb | 2135 | * v7_create_opts`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2136 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2137 | struct v7 *v7_create_opt(struct v7_create_opts opts); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2139 | /* Destroy V7 instance */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2140 | void v7_destroy(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2142 | /* Return root level (`global`) object of the given V7 instance. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2143 | v7_val_t v7_get_global(struct v7 *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2145 | /* Return current `this` object. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2146 | v7_val_t v7_get_this(struct v7 *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2147 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2148 | /* Return current `arguments` array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2149 | v7_val_t v7_get_arguments(struct v7 *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2151 | /* Return i-th argument */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2152 | v7_val_t v7_arg(struct v7 *v, unsigned long i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2154 | /* Return the length of `arguments` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2155 | unsigned long v7_argc(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2157 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2158 | * Tells the GC about a JS value variable/field owned |
Marko Mikulicic |
0:c0ecb8bf28eb | 2159 | * by C code. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2160 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2161 | * User C code should own v7_val_t variables |
Marko Mikulicic |
0:c0ecb8bf28eb | 2162 | * if the value's lifetime crosses any invocation |
Marko Mikulicic |
0:c0ecb8bf28eb | 2163 | * to the v7 runtime that creates new objects or new |
Marko Mikulicic |
0:c0ecb8bf28eb | 2164 | * properties and thus can potentially trigger GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2165 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2166 | * The registration of the variable prevents the GC from mistakenly treat |
Marko Mikulicic |
0:c0ecb8bf28eb | 2167 | * the object as garbage. The GC might be triggered potentially |
Marko Mikulicic |
0:c0ecb8bf28eb | 2168 | * allows the GC to update pointers |
Marko Mikulicic |
0:c0ecb8bf28eb | 2169 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2170 | * User code should also explicitly disown the variables with v7_disown once |
Marko Mikulicic |
0:c0ecb8bf28eb | 2171 | * it goes out of scope or the structure containing the v7_val_t field is freed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2172 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2173 | * Example: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2174 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2175 | * ``` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2176 | * struct v7_val cb; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2177 | * v7_own(v7, &cb); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2178 | * cb = v7_array_get(v7, args, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2179 | * // do something with cb |
Marko Mikulicic |
0:c0ecb8bf28eb | 2180 | * v7_disown(v7, &cb); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2181 | * ``` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2182 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2183 | void v7_own(struct v7 *v7, v7_val_t *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2185 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2186 | * Returns 1 if value is found, 0 otherwise |
Marko Mikulicic |
0:c0ecb8bf28eb | 2187 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2188 | int v7_disown(struct v7 *v7, v7_val_t *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2189 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2190 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2191 | * Enable or disable GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2192 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2193 | * Must be called before invoking v7_exec or v7_apply |
Marko Mikulicic |
0:c0ecb8bf28eb | 2194 | * from within a cfunction unless you know what you're doing. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2195 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2196 | * GC is disabled during execution of cfunctions in order to simplify |
Marko Mikulicic |
0:c0ecb8bf28eb | 2197 | * memory management of simple cfunctions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2198 | * However executing even small snippets of JS code causes a lot of memory |
Marko Mikulicic |
0:c0ecb8bf28eb | 2199 | * pressure. Enabling GC solves that but forces you to take care of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2200 | * reachability of your temporary V7 v7_val_t variables, as the GC needs |
Marko Mikulicic |
0:c0ecb8bf28eb | 2201 | * to know where they are since objects and strings can be either reclaimed |
Marko Mikulicic |
0:c0ecb8bf28eb | 2202 | * or relocated during a GC pass. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2203 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2204 | void v7_set_gc_enabled(struct v7 *v7, int enabled); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2205 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2206 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2207 | * Set an optional C stack limit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2208 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2209 | * It sets a flag that will cause the interpreter |
Marko Mikulicic |
0:c0ecb8bf28eb | 2210 | * to throw an InterruptedError. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2211 | * It's safe to call it from signal handlers and ISRs |
Marko Mikulicic |
0:c0ecb8bf28eb | 2212 | * on single threaded environments. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2213 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2214 | void v7_interrupt(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2216 | /* Returns last parser error message. TODO: rename it to `v7_get_error()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2217 | const char *v7_get_parser_error(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2218 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2219 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2220 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2221 | * Available if only `V7_ENABLE_STACK_TRACKING` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2222 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2223 | * Stack metric id. See `v7_stack_stat()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2224 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2225 | enum v7_stack_stat_what { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2226 | /* max stack size consumed by `i_exec()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2227 | V7_STACK_STAT_EXEC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2228 | /* max stack size consumed by `parse()` (which is called from `i_exec()`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2229 | V7_STACK_STAT_PARSER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2230 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2231 | V7_STACK_STATS_CNT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2232 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2233 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2234 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2235 | * Available if only `V7_ENABLE_STACK_TRACKING` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2236 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2237 | * Returns stack metric specified by the metric id `what`. See |
Marko Mikulicic |
0:c0ecb8bf28eb | 2238 | * `v7_stack_stat_clean()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2239 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2240 | int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2242 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2243 | * Available if only `V7_ENABLE_STACK_TRACKING` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2244 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2245 | * Clean all stack statistics gathered so far. See `v7_stack_stat()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2246 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2247 | void v7_stack_stat_clean(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2248 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2249 | |
Marko Mikulicic |
2:7762b98d31c7 | 2250 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 2251 | } |
Marko Mikulicic |
2:7762b98d31c7 | 2252 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 2253 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2254 | #endif /* CS_V7_SRC_CORE_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2255 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2256 | #line 1 "v7/src/std_error.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2257 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2258 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2259 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2260 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2261 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2263 | #ifndef CS_V7_SRC_STD_ERROR_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2264 | #define CS_V7_SRC_STD_ERROR_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2265 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2266 | /* Amalgamated: #include "v7/src/license.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2268 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2270 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2271 | * JavaScript error types |
Marko Mikulicic |
0:c0ecb8bf28eb | 2272 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2273 | #define TYPE_ERROR "TypeError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2274 | #define SYNTAX_ERROR "SyntaxError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2275 | #define REFERENCE_ERROR "ReferenceError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2276 | #define INTERNAL_ERROR "InternalError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2277 | #define RANGE_ERROR "RangeError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2278 | #define EVAL_ERROR "EvalError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2279 | #define ERROR_CTOR_MAX 6 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2280 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2281 | * TODO(mkm): EvalError is not so important, we should guard it behind |
Marko Mikulicic |
0:c0ecb8bf28eb | 2282 | * something like `V7_ENABLE__EvalError`. However doing so makes it hard to |
Marko Mikulicic |
0:c0ecb8bf28eb | 2283 | * keep ERROR_CTOR_MAX up to date; perhaps let's find a better way of doing it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2284 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2285 | * EvalError is useful mostly because we now have ecma tests failing: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2286 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2287 | * 8129 FAIL ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-7-c-iii-24.js (tail -c |
Marko Mikulicic |
0:c0ecb8bf28eb | 2288 | * +7600043 tests/ecmac.db|head -c 496): [{"message":"[EvalError] is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 2289 | * defined"}] |
Marko Mikulicic |
0:c0ecb8bf28eb | 2290 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2291 | * Those tests are not EvalError specific, and they do test that the exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 2292 | * handling machinery works as intended. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2293 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2295 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2296 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2297 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2299 | V7_PRIVATE void init_error(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2300 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2301 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2302 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2303 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2305 | #endif /* CS_V7_SRC_STD_ERROR_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2306 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2307 | #line 1 "v7/src/mm.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2308 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2309 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2310 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2311 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2312 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2314 | #ifndef CS_V7_SRC_MM_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2315 | #define CS_V7_SRC_MM_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2317 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2319 | typedef void (*gc_cell_destructor_t)(struct v7 *v7, void *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2321 | struct gc_block { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2322 | struct gc_block *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2323 | struct gc_cell *base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2324 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2325 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2327 | struct gc_arena { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2328 | struct gc_block *blocks; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2329 | size_t size_increment; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2330 | struct gc_cell *free; /* head of free list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2331 | size_t cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2333 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 2334 | unsigned long allocations; /* cumulative counter of allocations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2335 | unsigned long garbage; /* cumulative counter of garbage */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2336 | unsigned long alive; /* number of living cells */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2337 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2339 | gc_cell_destructor_t destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2341 | int verbose; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2342 | const char *name; /* for debugging purposes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2343 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2345 | #endif /* CS_V7_SRC_MM_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2346 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2347 | #line 1 "v7/src/parser.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2348 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2349 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2350 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2351 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2352 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2354 | #ifndef CS_V7_SRC_PARSER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2355 | #define CS_V7_SRC_PARSER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2357 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2358 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2360 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2362 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2363 | struct ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2365 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2366 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2367 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2369 | struct v7_pstate { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2370 | const char *file_name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2371 | const char *source_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2372 | const char *pc; /* Current parsing position */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2373 | const char *src_end; /* End of source code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2374 | int line_no; /* Line number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2375 | int prev_line_no; /* Line number of previous token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2376 | int inhibit_in; /* True while `in` expressions are inhibited */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2377 | int in_function; /* True if in a function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2378 | int in_loop; /* True if in a loop */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2379 | int in_switch; /* True if in a switch block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2380 | int in_strict; /* True if in strict mode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2381 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2383 | V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2384 | size_t src_len, int is_json); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2386 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2387 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2388 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2390 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2391 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2392 | #endif /* CS_V7_SRC_PARSER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2393 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2394 | #line 1 "v7/src/object_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2395 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2396 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2397 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2398 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2399 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2400 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2401 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2402 | * === Objects |
Marko Mikulicic |
0:c0ecb8bf28eb | 2403 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2405 | #ifndef CS_V7_SRC_OBJECT_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2406 | #define CS_V7_SRC_OBJECT_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2408 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2410 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2411 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2412 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2413 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2414 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2415 | * Property attributes bitmask |
Marko Mikulicic |
0:c0ecb8bf28eb | 2416 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2417 | typedef unsigned short v7_prop_attr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2418 | #define V7_PROPERTY_NON_WRITABLE (1 << 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2419 | #define V7_PROPERTY_NON_ENUMERABLE (1 << 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2420 | #define V7_PROPERTY_NON_CONFIGURABLE (1 << 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2421 | #define V7_PROPERTY_GETTER (1 << 3) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2422 | #define V7_PROPERTY_SETTER (1 << 4) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2423 | #define _V7_PROPERTY_HIDDEN (1 << 5) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2424 | /* property not managed by V7 HEAP */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2425 | #define _V7_PROPERTY_OFF_HEAP (1 << 6) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2426 | /* special property holding user data and destructor cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2427 | #define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR (1 << 7) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2428 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2429 | * not a property attribute, but a flag for `v7_def()`. It's here in order to |
Marko Mikulicic |
0:c0ecb8bf28eb | 2430 | * keep all offsets in one place |
Marko Mikulicic |
0:c0ecb8bf28eb | 2431 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2432 | #define _V7_DESC_PRESERVE_VALUE (1 << 8) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2434 | #define V7_PROP_ATTR_IS_WRITABLE(a) (!(a & V7_PROPERTY_NON_WRITABLE)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2435 | #define V7_PROP_ATTR_IS_ENUMERABLE(a) (!(a & V7_PROPERTY_NON_ENUMERABLE)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2436 | #define V7_PROP_ATTR_IS_CONFIGURABLE(a) (!(a & V7_PROPERTY_NON_CONFIGURABLE)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2438 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2439 | * Internal helpers for `V7_DESC_...` macros |
Marko Mikulicic |
0:c0ecb8bf28eb | 2440 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2441 | #define _V7_DESC_SHIFT 16 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2442 | #define _V7_DESC_MASK ((1 << _V7_DESC_SHIFT) - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2443 | #define _V7_MK_DESC(v, n) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2444 | (((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2445 | #define _V7_MK_DESC_INV(v, n) _V7_MK_DESC(!(v), (n)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2446 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2447 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2448 | * Property attribute descriptors that may be given to `v7_def()`: for each |
Marko Mikulicic |
0:c0ecb8bf28eb | 2449 | * attribute (`v7_prop_attr_t`), there is a corresponding macro, which takes |
Marko Mikulicic |
0:c0ecb8bf28eb | 2450 | * param: either 1 (set attribute) or 0 (clear attribute). If some particular |
Marko Mikulicic |
0:c0ecb8bf28eb | 2451 | * attribute isn't mentioned at all, it's left unchanged (or default, if the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2452 | * property is being created) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2453 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2454 | * There is additional flag: `V7_DESC_PRESERVE_VALUE`. If it is set, the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2455 | * property value isn't changed (or set to `undefined` if the property is being |
Marko Mikulicic |
0:c0ecb8bf28eb | 2456 | * created) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2457 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2458 | typedef unsigned long v7_prop_attr_desc_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2459 | #define V7_DESC_WRITABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2460 | #define V7_DESC_ENUMERABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2461 | #define V7_DESC_CONFIGURABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2462 | #define V7_DESC_GETTER(v) _V7_MK_DESC(v, V7_PROPERTY_GETTER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2463 | #define V7_DESC_SETTER(v) _V7_MK_DESC(v, V7_PROPERTY_SETTER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2464 | #define V7_DESC_PRESERVE_VALUE _V7_DESC_PRESERVE_VALUE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2466 | #define _V7_DESC_HIDDEN(v) _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2467 | #define _V7_DESC_OFF_HEAP(v) _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2469 | /* See `v7_set_destructor_cb` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2470 | typedef void(v7_destructor_cb_t)(struct v7 *v7, void *ud); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2472 | /* Make an empty object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2473 | v7_val_t v7_mk_object(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2475 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2476 | * Returns true if the given value is an object or function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2477 | * i.e. it returns true if the value holds properties and can be |
Marko Mikulicic |
0:c0ecb8bf28eb | 2478 | * used as argument to `v7_get`, `v7_set` and `v7_def`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2479 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2480 | int v7_is_object(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2481 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2482 | /* Set object's prototype. Return old prototype or undefined on error. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2483 | v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2484 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2485 | /* Get object's prototype. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2486 | v7_val_t v7_get_proto(struct v7 *v7, v7_val_t obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2488 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2489 | * Lookup property `name` in object `obj`. If `obj` holds no such property, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2490 | * an `undefined` value is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2491 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2492 | * If `name_len` is ~0, `name` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 2493 | * `strlen(name)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2494 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2495 | v7_val_t v7_get(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2496 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2497 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2498 | * Like `v7_get()`, but "returns" value through `res` pointer argument. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2499 | * `res` must not be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2500 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2501 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 2502 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2503 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2504 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2505 | enum v7_err v7_get_throwing(struct v7 *v7, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2506 | size_t name_len, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2508 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2509 | * Define object property, similar to JavaScript `Object.defineProperty()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2510 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2511 | * `name`, `name_len` specify property name, `val` is a property value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2512 | * `attrs_desc` is a set of flags which can affect property's attributes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2513 | * see comment of `v7_prop_attr_desc_t` for details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2514 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2515 | * If `name_len` is ~0, `name` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 2516 | * `strlen(name)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2517 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2518 | * Returns non-zero on success, 0 on error (e.g. out of memory). |
Marko Mikulicic |
0:c0ecb8bf28eb | 2519 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2520 | * See also `v7_set()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2521 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2522 | int v7_def(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2523 | v7_prop_attr_desc_t attrs_desc, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2525 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2526 | * Set object property. Behaves just like JavaScript assignment. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2527 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2528 | * See also `v7_def()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2529 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2530 | int v7_set(struct v7 *v7, v7_val_t obj, const char *name, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2531 | v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2533 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2534 | * A helper function to define object's method backed by a C function `func`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2535 | * `name` must be NUL-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2536 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2537 | * Return value is the same as for `v7_set()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2538 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2539 | int v7_set_method(struct v7 *, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2540 | v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2542 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2543 | * Delete own property `name` of the object `obj`. Does not follow the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2544 | * prototype chain. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2545 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2546 | * If `name_len` is ~0, `name` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 2547 | * `strlen(name)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2548 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2549 | * Returns 0 on success, -1 on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2550 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2551 | int v7_del(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2552 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2553 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 2554 | struct prop_iter_proxy_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2555 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2557 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2558 | * Context for property iteration, see `v7_next_prop()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2559 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2560 | * Clients should not interpret contents of this structure, it's here merely to |
Marko Mikulicic |
0:c0ecb8bf28eb | 2561 | * allow clients to allocate it not from the heap. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2562 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2563 | struct prop_iter_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2564 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 2565 | struct prop_iter_proxy_ctx *proxy_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2566 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2567 | struct v7_property *cur_prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2568 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2569 | unsigned init : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2570 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2572 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2573 | * Initialize the property iteration context `ctx`, see `v7_next_prop()` for |
Marko Mikulicic |
0:c0ecb8bf28eb | 2574 | * usage example. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2575 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2576 | enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2577 | struct prop_iter_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2578 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2579 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2580 | * Destruct the property iteration context `ctx`, see `v7_next_prop()` for |
Marko Mikulicic |
0:c0ecb8bf28eb | 2581 | * usage example |
Marko Mikulicic |
0:c0ecb8bf28eb | 2582 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2583 | void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2584 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2585 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2586 | * Iterate over the `obj`'s properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2587 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2588 | * Usage example (here we assume we have some `v7_val_t obj`): |
Marko Mikulicic |
0:c0ecb8bf28eb | 2589 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2590 | * struct prop_iter_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2591 | * v7_val_t name, val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2592 | * v7_prop_attr_t attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2593 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2594 | * v7_init_prop_iter_ctx(v7, obj, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2595 | * while (v7_next_prop(v7, &ctx, &name, &val, &attrs)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2596 | * if (V7_PROP_ATTR_IS_ENUMERABLE(attrs)) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2597 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 2598 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2599 | * v7_destruct_prop_iter_ctx(v7, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2600 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2601 | * As you see, v7_next_prop will iterate through all properties, including |
Marko Mikulicic |
0:c0ecb8bf28eb | 2602 | * non-enumerable ones, and it's your responsibility to test the attributes |
Marko Mikulicic |
0:c0ecb8bf28eb | 2603 | * with the provided `V7_PROP_ATTR_*` macros and proceed as you see fit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2604 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2605 | int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2606 | v7_val_t *value, v7_prop_attr_t *attrs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2607 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2608 | /* Returns true if the object is an instance of a given constructor. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2609 | int v7_is_instanceof(struct v7 *v7, v7_val_t o, const char *c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2611 | /* Returns true if the object is an instance of a given constructor. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2612 | int v7_is_instanceof_v(struct v7 *v7, v7_val_t o, v7_val_t c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2614 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2615 | * Associates an opaque C value (anything that can be casted to a `void * ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2616 | * with an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2617 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2618 | * You can achieve a similar effect by just setting a special property with |
Marko Mikulicic |
0:c0ecb8bf28eb | 2619 | * a foreign value (see `v7_mk_foreign`), except user data offers the following |
Marko Mikulicic |
0:c0ecb8bf28eb | 2620 | * advantages: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2621 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2622 | * 1. You don't have to come up with some arbitrary "special" property name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2623 | * 2. JS scripts cannot access user data by mistake via property lookup. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2624 | * 3. The user data is available to the destructor. When the desctructor is |
Marko Mikulicic |
0:c0ecb8bf28eb | 2625 | * invoked you cannot access any of its properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2626 | * 4. Allows the implementation to use a more compact encoding |
Marko Mikulicic |
0:c0ecb8bf28eb | 2627 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2628 | * Does nothing if `obj` is not a mutable object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2629 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2630 | void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2632 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2633 | * Get the opaque user data set with `v7_set_user_data`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2634 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2635 | * Returns NULL if there is no user data set or if `obj` is not an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2636 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2637 | void *v7_get_user_data(struct v7 *v7, v7_val_t obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2638 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2639 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2640 | * Register a callback which will be invoked when a given object gets |
Marko Mikulicic |
0:c0ecb8bf28eb | 2641 | * reclaimed by the garbage collector. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2642 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2643 | * The callback will be invoked while garbage collection is still in progress |
Marko Mikulicic |
0:c0ecb8bf28eb | 2644 | * and hence the internal state of the JS heap is in an undefined state. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2645 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2646 | * The only v7 API which is safe to use in this callback is `v7_disown()`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2647 | * that's why `v7` pointer is given to it. *Calls to any other v7 functions are |
Marko Mikulicic |
0:c0ecb8bf28eb | 2648 | * illegal here*. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2649 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2650 | * The intended use case is to reclaim resources allocated by C code. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2651 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2652 | void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2654 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2655 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2656 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2657 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2658 | #endif /* CS_V7_SRC_OBJECT_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2659 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2660 | #line 1 "v7/src/tokenizer.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2661 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2662 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2663 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2664 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2665 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2667 | #ifndef CS_V7_SRC_TOKENIZER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2668 | #define CS_V7_SRC_TOKENIZER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2670 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2672 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2674 | enum v7_tok { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2675 | TOK_END_OF_INPUT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2676 | TOK_NUMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2677 | TOK_STRING_LITERAL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2678 | TOK_REGEX_LITERAL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2679 | TOK_IDENTIFIER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2680 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2681 | /* Punctuators */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2682 | TOK_OPEN_CURLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2683 | TOK_CLOSE_CURLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2684 | TOK_OPEN_PAREN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2685 | TOK_CLOSE_PAREN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2686 | TOK_COMMA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2687 | TOK_OPEN_BRACKET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2688 | TOK_CLOSE_BRACKET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2689 | TOK_DOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2690 | TOK_COLON, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2691 | TOK_SEMICOLON, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2693 | /* Equality ops, in this order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2694 | TOK_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2695 | TOK_EQ_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2696 | TOK_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2697 | TOK_NE_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2699 | /* Assigns */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2700 | TOK_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2701 | TOK_REM_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2702 | TOK_MUL_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2703 | TOK_DIV_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2704 | TOK_XOR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2705 | TOK_PLUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2706 | TOK_MINUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2707 | TOK_OR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2708 | TOK_AND_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2709 | TOK_LSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2710 | TOK_RSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2711 | TOK_URSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2712 | TOK_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2713 | TOK_LOGICAL_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2714 | TOK_PLUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2715 | TOK_MINUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2716 | TOK_PLUS_PLUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2717 | TOK_MINUS_MINUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2718 | TOK_LOGICAL_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2719 | TOK_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2720 | TOK_QUESTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2721 | TOK_TILDA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2722 | TOK_REM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2723 | TOK_MUL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2724 | TOK_DIV, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2725 | TOK_XOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2727 | /* Relational ops, must go in this order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2728 | TOK_LE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2729 | TOK_LT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2730 | TOK_GE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2731 | TOK_GT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2732 | TOK_LSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2733 | TOK_RSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2734 | TOK_URSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2735 | TOK_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2736 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2737 | /* Keywords. must be in the same order as tokenizer.c::s_keywords array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2738 | TOK_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2739 | TOK_CASE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2740 | TOK_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2741 | TOK_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2742 | TOK_DEBUGGER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2743 | TOK_DEFAULT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2744 | TOK_DELETE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2745 | TOK_DO, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2746 | TOK_ELSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2747 | TOK_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2748 | TOK_FINALLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2749 | TOK_FOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2750 | TOK_FUNCTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2751 | TOK_IF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2752 | TOK_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2753 | TOK_INSTANCEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2754 | TOK_NEW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2755 | TOK_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2756 | TOK_RETURN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2757 | TOK_SWITCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2758 | TOK_THIS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2759 | TOK_THROW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2760 | TOK_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2761 | TOK_TRY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2762 | TOK_TYPEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2763 | TOK_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2764 | TOK_VOID, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2765 | TOK_WHILE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2766 | TOK_WITH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2768 | /* TODO(lsm): process these reserved words too */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2769 | TOK_CLASS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2770 | TOK_ENUM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2771 | TOK_EXTENDS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2772 | TOK_SUPER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2773 | TOK_CONST, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2774 | TOK_EXPORT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2775 | TOK_IMPORT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2776 | TOK_IMPLEMENTS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2777 | TOK_LET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2778 | TOK_PRIVATE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2779 | TOK_PUBLIC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2780 | TOK_INTERFACE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2781 | TOK_PACKAGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2782 | TOK_PROTECTED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2783 | TOK_STATIC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2784 | TOK_YIELD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2786 | NUM_TOKENS |
Marko Mikulicic |
0:c0ecb8bf28eb | 2787 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2789 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2790 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2791 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2793 | V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2794 | V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2795 | enum v7_tok prev_tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2796 | V7_PRIVATE int is_reserved_word_token(enum v7_tok tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2798 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2799 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2800 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2802 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2804 | #endif /* CS_V7_SRC_TOKENIZER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2805 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2806 | #line 1 "v7/src/opcodes.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2807 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2808 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2809 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2810 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2811 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2813 | #ifndef CS_V7_SRC_OPCODES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2814 | #define CS_V7_SRC_OPCODES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2816 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2817 | * ==== Instructions |
Marko Mikulicic |
0:c0ecb8bf28eb | 2818 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2819 | * Bytecode instructions consist of 1-byte opcode, optionally followed by N |
Marko Mikulicic |
0:c0ecb8bf28eb | 2820 | * bytes of arguments. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2821 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2822 | * Opcodes that accept an index in the literal table (PUSH_LIT, GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2823 | * SET_VAR, ...) also accept inline literals. In order to distinguish indices in |
Marko Mikulicic |
0:c0ecb8bf28eb | 2824 | * the literals table and the inline literals, indices 0 and 1 are reserved as |
Marko Mikulicic |
0:c0ecb8bf28eb | 2825 | * type tags for inline literals: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2826 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2827 | * if 0, the following bytes encode a string literal |
Marko Mikulicic |
0:c0ecb8bf28eb | 2828 | * if 1, they encode a number (textual, like in the AST) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2829 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2830 | * (see enum bcode_inline_lit_type_tag) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2831 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2832 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2833 | * Stack diagrams follow the syntax and semantics of: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2834 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2835 | * http://everything2.com/title/Forth+stack+diagrams[Forth stack diagrams]. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2836 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2837 | * We use the following extension in the terminology: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2838 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2839 | * `T`: "Try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 2840 | * `A`: opcode arguments. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2841 | * `S`: stash register (one element stack). |
Marko Mikulicic |
0:c0ecb8bf28eb | 2842 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2843 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2844 | enum opcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2845 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2846 | * Removes an item from the top of the stack. It is undefined what happens if |
Marko Mikulicic |
0:c0ecb8bf28eb | 2847 | * the stack is empty. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2848 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2849 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2850 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2851 | OP_DROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2852 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2853 | * Duplicates a value on top of the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2854 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2855 | * `( a -- a a)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2856 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2857 | OP_DUP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2858 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2859 | * Duplicates 2 values from the top of the stack in the same order. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2860 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2861 | * `( a b -- a b a b)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2862 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2863 | OP_2DUP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2864 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2865 | * Swap the top two items on the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2866 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2867 | * `( a b -- b a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2868 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2869 | OP_SWAP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2870 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2871 | * Copy current top of the stack to the temporary stash register. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2872 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2873 | * The content of the stash register will be cleared in the event of an |
Marko Mikulicic |
0:c0ecb8bf28eb | 2874 | * exception. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2875 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2876 | * `( a S: b -- a S: a)` saves TOS to stash reg |
Marko Mikulicic |
0:c0ecb8bf28eb | 2877 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2878 | OP_STASH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2879 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2880 | * Replace the top of the stack with the content of the temporary stash |
Marko Mikulicic |
0:c0ecb8bf28eb | 2881 | * register. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2882 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2883 | * The stash register is cleared afterwards. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2884 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2885 | * `( a S: b -- b S: nil )` replaces tos with stash reg |
Marko Mikulicic |
0:c0ecb8bf28eb | 2886 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2887 | OP_UNSTASH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2889 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2890 | * Effectively drops the last-but-one element from stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 2891 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2892 | * `( a b -- b )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2893 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2894 | OP_SWAP_DROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2895 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2896 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2897 | * Pushes `undefined` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2898 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2899 | * `( -- undefined )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2900 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2901 | OP_PUSH_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2902 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2903 | * Pushes `null` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2904 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2905 | * `( -- null )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2906 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2907 | OP_PUSH_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2908 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2909 | * Pushes current value of `this` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2910 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2911 | * `( -- this )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2912 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2913 | OP_PUSH_THIS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2914 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2915 | * Pushes `true` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2916 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2917 | * `( -- true )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2918 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2919 | OP_PUSH_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2920 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2921 | * Pushes `false` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2922 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2923 | * `( -- false )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2924 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2925 | OP_PUSH_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2926 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2927 | * Pushes `0` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2928 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2929 | * `( -- 0 )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2930 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2931 | OP_PUSH_ZERO, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2932 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2933 | * Pushes `1` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2934 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2935 | * `( -- 1 )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2936 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2937 | OP_PUSH_ONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2939 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2940 | * Pushes a value from literals table onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2941 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2942 | * The opcode takes a varint operand interpreted as an index in the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 2943 | * literal table (see lit table). |
Marko Mikulicic |
0:c0ecb8bf28eb | 2944 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2945 | * ( -- a ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2946 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2947 | OP_PUSH_LIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2948 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2949 | OP_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2950 | OP_LOGICAL_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2952 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2953 | * Takes a number from the top of the stack, inverts the sign and pushes it |
Marko Mikulicic |
0:c0ecb8bf28eb | 2954 | * back. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2955 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2956 | * `( a -- -a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2957 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2958 | OP_NEG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2959 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2960 | * Takes a number from the top of the stack pushes the evaluation of |
Marko Mikulicic |
0:c0ecb8bf28eb | 2961 | * `Number()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2962 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2963 | * `( a -- Number(a) )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2964 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2965 | OP_POS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2967 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2968 | * Takes 2 values from the top of the stack and performs addition operation: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2969 | * If any of the two values is not `undefined`, number or boolean, both values |
Marko Mikulicic |
0:c0ecb8bf28eb | 2970 | * are converted into strings and concatenated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2971 | * Otherwise, both values are treated as numbers: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2972 | * * `undefined` is converted into NaN |
Marko Mikulicic |
0:c0ecb8bf28eb | 2973 | * * `true` is converted into 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2974 | * * `false` is converted into 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2975 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2976 | * Result is pushed back onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2977 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2978 | * TODO: make it behave exactly like JavaScript's `+` operator. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2979 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2980 | * `( a b -- a+b )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2981 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2982 | OP_ADD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2983 | OP_SUB, /* ( a b -- a-b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2984 | OP_REM, /* ( a b -- a%b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2985 | OP_MUL, /* ( a b -- a*b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2986 | OP_DIV, /* ( a b -- a/b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2987 | OP_LSHIFT, /* ( a b -- a<<b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2988 | OP_RSHIFT, /* ( a b -- a>>b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2989 | OP_URSHIFT, /* ( a b -- a>>>b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2990 | OP_OR, /* ( a b -- a|b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2991 | OP_XOR, /* ( a b -- a^b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2992 | OP_AND, /* ( a b -- a&b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2994 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2995 | * Takes two numbers form the top of the stack and pushes `true` if they are |
Marko Mikulicic |
0:c0ecb8bf28eb | 2996 | * equal, or `false` if they are not equal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2997 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2998 | * ( a b -- a===b ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2999 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3000 | OP_EQ_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3001 | OP_EQ, /* ( a b -- a==b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3002 | OP_NE, /* ( a b -- a!=b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3003 | OP_NE_NE, /* ( a b -- a!==b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3004 | OP_LT, /* ( a b -- a<b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3005 | OP_LE, /* ( a b -- a<=b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3006 | OP_GT, /* ( a b -- a>b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3007 | OP_GE, /* ( a b -- a>=b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3008 | OP_INSTANCEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3010 | OP_TYPEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3012 | OP_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3013 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3014 | * Takes 2 values from the stack, treats the top of the stack as property name |
Marko Mikulicic |
0:c0ecb8bf28eb | 3015 | * and the next value must be an object, an array or a string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3016 | * If it's an object, pushes the value of its named property onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3017 | * If it's an array or a string, returns a value at a given position. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3018 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3019 | OP_GET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3020 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3021 | * Takes 3 items from the stack: value, property name, object. Sets the given |
Marko Mikulicic |
0:c0ecb8bf28eb | 3022 | * property of a given object to a given value, pushes value back onto the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3023 | *stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3024 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3025 | * `( a b c -- a[b]=c )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3026 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3027 | OP_SET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3028 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3029 | * Takes 1 value from the stack and a varint argument -- index of the var name |
Marko Mikulicic |
0:c0ecb8bf28eb | 3030 | * in the literals table. Tries to find the variable in the current scope |
Marko Mikulicic |
0:c0ecb8bf28eb | 3031 | * chain and assign the value to it. If the varialble is not found -- creates |
Marko Mikulicic |
0:c0ecb8bf28eb | 3032 | * a new one in the global scope. Pushes the value back to the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3033 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3034 | * `( a -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3035 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3036 | OP_SET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3037 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3038 | * Takes a varint argument -- index of the var name in the literals table. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3039 | * Looks up that variable in the scope chain and pushes its value onto the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3040 | * stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3041 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3042 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3043 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3044 | OP_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3046 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3047 | * Like OP_GET_VAR but returns undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 3048 | * instead of throwing reference error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3049 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3050 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3051 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3052 | OP_SAFE_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3054 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3055 | * ==== Jumps |
Marko Mikulicic |
0:c0ecb8bf28eb | 3056 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3057 | * All jump instructions take one 4-byte argument: offset to jump to. Offset |
Marko Mikulicic |
0:c0ecb8bf28eb | 3058 | *is a |
Marko Mikulicic |
0:c0ecb8bf28eb | 3059 | * index of the byte in the instruction stream, starting with 0. No byte order |
Marko Mikulicic |
0:c0ecb8bf28eb | 3060 | * conversion is applied. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3061 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3062 | * TODO: specify byte order for the offset. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3063 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3065 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3066 | * Unconditiona jump. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3067 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3068 | OP_JMP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3069 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3070 | * Takes one value from the stack and performs a jump if conversion of that |
Marko Mikulicic |
0:c0ecb8bf28eb | 3071 | * value to boolean results in `true`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3072 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3073 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3074 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3075 | OP_JMP_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3076 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3077 | * Takes one value from the stack and performs a jump if conversion of that |
Marko Mikulicic |
0:c0ecb8bf28eb | 3078 | * value to boolean results in `false`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3079 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3080 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3081 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3082 | OP_JMP_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3083 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3084 | * Like OP_JMP_TRUE but if the branch |
Marko Mikulicic |
0:c0ecb8bf28eb | 3085 | * is taken it also drops another stack element: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3086 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3087 | * if `b` is true: `( a b -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3088 | * if `b` is false: `( a b -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3089 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3090 | OP_JMP_TRUE_DROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3091 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3092 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3093 | * Conditional jump on the v7->is_continuing flag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3094 | * Clears the flag once executed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3095 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3096 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3097 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3098 | OP_JMP_IF_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3099 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3100 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3101 | * Constructs a new empty object and pushes it onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3102 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3103 | * `( -- {} )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3104 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3105 | OP_CREATE_OBJ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3106 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3107 | * Constructs a new empty array and pushes it onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3108 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3109 | * `( -- [] )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3110 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3111 | OP_CREATE_ARR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3113 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3114 | * Allocates the iteration context (for `OP_NEXT_PROP`) from heap and pushes |
Marko Mikulicic |
0:c0ecb8bf28eb | 3115 | * a foreign pointer to it on stack. The allocated data is stored as "user |
Marko Mikulicic |
0:c0ecb8bf28eb | 3116 | * data" of the object, and it will be reclaimed automatically when the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3117 | * object gets garbage-collected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3118 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3119 | * `( -- ctx )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3120 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3121 | OP_PUSH_PROP_ITER_CTX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3123 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3124 | * Yields the next property name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3125 | * Used in the for..in construct. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3126 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3127 | * The first evaluation must receive `null` as handle. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3128 | * Subsequent evaluations will either: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3129 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3130 | * a) produce a new handle, the key and true value: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3131 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3132 | * `( o h -- o h' key true)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3133 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3134 | * b) produce a false value only, indicating no more properties: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3135 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3136 | * `( o h -- false)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3137 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3138 | OP_NEXT_PROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3140 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3141 | * Copies the function object at TOS and assigns current scope |
Marko Mikulicic |
0:c0ecb8bf28eb | 3142 | * in func->scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3143 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3144 | * `( a -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3145 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3146 | OP_FUNC_LIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3147 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3148 | * Takes the number of arguments as parameter. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3149 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3150 | * Pops N function arguments from stack, then pops function, then pops `this`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3151 | * Calls a function and populates TOS with the returned value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3152 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3153 | * `( this f a0 a1 ... aN -- f(a0,a1,...) )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3154 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3155 | OP_CALL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3156 | OP_NEW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3157 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3158 | * Checks that TOS is a callable and if not saves an exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 3159 | * that will will be thrown by CALL after all arguments have been evaluated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3160 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3161 | OP_CHECK_CALL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3162 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3163 | * Returns the current function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3164 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3165 | * It has no stack side effects. The function upon return will leave the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3166 | * return value on the stack. The return value must be pushed on the stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 3167 | * prior to invoking a RET. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3168 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3169 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3170 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3171 | OP_RET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3173 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3174 | * Deletes the property of given name `p` from the given object `o`. Returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 3175 | * boolean value `a`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3176 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3177 | * `( o p -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3178 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3179 | OP_DELETE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3180 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3181 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3182 | * Like `OP_DELETE`, but uses the current scope as an object to delete |
Marko Mikulicic |
0:c0ecb8bf28eb | 3183 | * a property from. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3184 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3185 | * `( p -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3186 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3187 | OP_DELETE_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3189 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3190 | * Pushes a value (bcode offset of `catch` block) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3191 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3192 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3193 | * Used in the beginning of the `try` block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3194 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3195 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3196 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3197 | OP_TRY_PUSH_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3199 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3200 | * Pushes a value (bcode offset of `finally` block) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3201 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3202 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3203 | * Used in the beginning of the `try` block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3204 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3205 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3206 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3207 | * TODO: implement me |
Marko Mikulicic |
0:c0ecb8bf28eb | 3208 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3209 | OP_TRY_PUSH_FINALLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3210 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3211 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3212 | * Pushes a value (bcode offset of a label) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3213 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3214 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3215 | * Used at the beginning of loops that contain break or continue. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3216 | * Possible optimisation: don't emit if we can ensure that no break or |
Marko Mikulicic |
0:c0ecb8bf28eb | 3217 | * continue statement is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3218 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3219 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3220 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3221 | OP_TRY_PUSH_LOOP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3223 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3224 | * Pushes a value (bcode offset of a label) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3225 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3226 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3227 | * Used at the beginning of switch statements. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3228 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3229 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3230 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3231 | OP_TRY_PUSH_SWITCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3232 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3233 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3234 | * Pops a value (bcode offset of `finally` or `catch` block) from "try |
Marko Mikulicic |
0:c0ecb8bf28eb | 3235 | * stack", and discards it |
Marko Mikulicic |
0:c0ecb8bf28eb | 3236 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3237 | * Used in the end of the `try` block, as well as in the beginning of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3238 | * `catch` and `finally` blocks |
Marko Mikulicic |
0:c0ecb8bf28eb | 3239 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3240 | * `( T: a -- T: )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3241 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3242 | OP_TRY_POP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3244 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3245 | * Used in the end of the `finally` block: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3246 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3247 | * - if some value is currently being thrown, keep throwing it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3248 | * If eventually we encounter `catch` block, the thrown value gets |
Marko Mikulicic |
0:c0ecb8bf28eb | 3249 | * populated on TOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3250 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3251 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3252 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3253 | * - if there is some pending value to return, keep returning it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3254 | * If we encounter no further `finally` blocks, then the returned value |
Marko Mikulicic |
0:c0ecb8bf28eb | 3255 | * gets populated on TOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3256 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3257 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3258 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3259 | * And return is performed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3260 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3261 | * - otherwise, do nothing |
Marko Mikulicic |
0:c0ecb8bf28eb | 3262 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3263 | OP_AFTER_FINALLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3264 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3265 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3266 | * Throw value from TOS. First of all, it pops the value and saves it into |
Marko Mikulicic |
0:c0ecb8bf28eb | 3267 | * `v7->vals.thrown_error`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3268 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3269 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3270 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3271 | * Then unwinds stack looking for the first `catch` or `finally` blocks. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3272 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3273 | * - if `finally` is found, thrown value is kept into `v7->vals.thrown_error`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3274 | * - if `catch` is found, thrown value is pushed back to the stack: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3275 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3276 | * - otherwise, thrown value is kept into `v7->vals.thrown_error` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3277 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3278 | OP_THROW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3280 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3281 | * Unwind to next break entry in the try stack, evaluating |
Marko Mikulicic |
0:c0ecb8bf28eb | 3282 | * all finally blocks on its way up. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3283 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3284 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3285 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3286 | OP_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3288 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3289 | * Like OP_BREAK, but sets the v7->is_continuing flag |
Marko Mikulicic |
0:c0ecb8bf28eb | 3290 | * which will cause OP_JMP_IF_CONTINUE to restart the loop. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3291 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3292 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3293 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3294 | OP_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3296 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3297 | * Used when we enter the `catch` block. Takes a varint argument -- index of |
Marko Mikulicic |
0:c0ecb8bf28eb | 3298 | * the exception variable name in the literals table. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3299 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3300 | * Pops the exception value from the stack, creates a private frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3301 | * sets exception property on it with the given name. pushes this |
Marko Mikulicic |
0:c0ecb8bf28eb | 3302 | * private frame to call stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3303 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3304 | * `( e -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3305 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3306 | OP_ENTER_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3308 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3309 | * Ued when we exit from the `catch` block. Merely pops the private frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 3310 | * from the call stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3311 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3312 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3313 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3314 | OP_EXIT_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3316 | OP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3317 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3319 | #define _OP_LINE_NO 0x80 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3321 | #endif /* CS_V7_SRC_OPCODES_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3322 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 3323 | #line 1 "v7/src/core.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 3324 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3325 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3326 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 3327 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 3328 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3330 | #ifndef CS_V7_SRC_CORE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3331 | #define CS_V7_SRC_CORE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3333 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3334 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3335 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3336 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3337 | /* Amalgamated: #include "v7/src/mm.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3338 | /* Amalgamated: #include "v7/src/parser.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3339 | /* Amalgamated: #include "v7/src/object_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3340 | /* Amalgamated: #include "v7/src/tokenizer.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3341 | /* Amalgamated: #include "v7/src/opcodes.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3343 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3344 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3345 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3347 | typedef uint64_t val_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3348 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3349 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3351 | typedef unsigned short entity_id_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3352 | typedef unsigned char entity_id_part_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3354 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3355 | * Magic numbers that are stored in various objects in order to identify their |
Marko Mikulicic |
0:c0ecb8bf28eb | 3356 | * type in runtime |
Marko Mikulicic |
0:c0ecb8bf28eb | 3357 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3358 | #define V7_ENTITY_ID_PROP 0xe9a1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3359 | #define V7_ENTITY_ID_PART_OBJ 0x57 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3360 | #define V7_ENTITY_ID_PART_GEN_OBJ 0x31 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3361 | #define V7_ENTITY_ID_PART_JS_FUNC 0x0d |
Marko Mikulicic |
0:c0ecb8bf28eb | 3362 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3363 | #define V7_ENTITY_ID_NONE 0xa5a5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3364 | #define V7_ENTITY_ID_PART_NONE 0xa5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3366 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3367 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3368 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3369 | * Double-precision floating-point number, IEEE 754 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3370 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3371 | * 64 bit (8 bytes) in total |
Marko Mikulicic |
0:c0ecb8bf28eb | 3372 | * 1 bit sign |
Marko Mikulicic |
0:c0ecb8bf28eb | 3373 | * 11 bits exponent |
Marko Mikulicic |
0:c0ecb8bf28eb | 3374 | * 52 bits mantissa |
Marko Mikulicic |
0:c0ecb8bf28eb | 3375 | * 7 6 5 4 3 2 1 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3376 | * seeeeeee|eeeemmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm |
Marko Mikulicic |
0:c0ecb8bf28eb | 3377 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3378 | * If an exponent is all-1 and mantissa is all-0, then it is an INFINITY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3379 | * 11111111|11110000|00000000|00000000|00000000|00000000|00000000|00000000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3380 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3381 | * If an exponent is all-1 and mantissa's MSB is 1, it is a quiet NaN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3382 | * 11111111|11111000|00000000|00000000|00000000|00000000|00000000|00000000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3383 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3384 | * V7 NaN-packing: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3385 | * sign and exponent is 0xfff |
Marko Mikulicic |
0:c0ecb8bf28eb | 3386 | * 4 bits specify type (tag), must be non-zero |
Marko Mikulicic |
0:c0ecb8bf28eb | 3387 | * 48 bits specify value |
Marko Mikulicic |
0:c0ecb8bf28eb | 3388 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3389 | * 11111111|1111tttt|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv |
Marko Mikulicic |
0:c0ecb8bf28eb | 3390 | * NaN marker |type| 48-bit placeholder for values: pointers, strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 3391 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3392 | * On 64-bit platforms, pointers are really 48 bit only, so they can fit, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3393 | * provided they are sign extended |
Marko Mikulicic |
0:c0ecb8bf28eb | 3394 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3396 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3397 | * A tag is made of the sign bit and the 4 lower order bits of byte 6. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3398 | * So in total we have 32 possible tags. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3399 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3400 | * Tag (1,0) however cannot hold a zero payload otherwise it's interpreted as an |
Marko Mikulicic |
0:c0ecb8bf28eb | 3401 | * INFINITY; for simplicity we're just not going to use that combination. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3402 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3403 | #define MAKE_TAG(s, t) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3404 | ((uint64_t)(s) << 63 | (uint64_t) 0x7ff0 << 48 | (uint64_t)(t) << 48) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3406 | #define V7_TAG_OBJECT MAKE_TAG(1, 0xF) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3407 | #define V7_TAG_FOREIGN MAKE_TAG(1, 0xE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3408 | #define V7_TAG_UNDEFINED MAKE_TAG(1, 0xD) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3409 | #define V7_TAG_BOOLEAN MAKE_TAG(1, 0xC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3410 | #define V7_TAG_NAN MAKE_TAG(1, 0xB) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3411 | #define V7_TAG_STRING_I MAKE_TAG(1, 0xA) /* Inlined string len < 5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3412 | #define V7_TAG_STRING_5 MAKE_TAG(1, 0x9) /* Inlined string len 5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3413 | #define V7_TAG_STRING_O MAKE_TAG(1, 0x8) /* Owned string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3414 | #define V7_TAG_STRING_F MAKE_TAG(1, 0x7) /* Foreign string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3415 | #define V7_TAG_STRING_C MAKE_TAG(1, 0x6) /* String chunk */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3416 | #define V7_TAG_FUNCTION MAKE_TAG(1, 0x5) /* JavaScript function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3417 | #define V7_TAG_CFUNCTION MAKE_TAG(1, 0x4) /* C function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3418 | #define V7_TAG_STRING_D MAKE_TAG(1, 0x3) /* Dictionary string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3419 | #define V7_TAG_REGEXP MAKE_TAG(1, 0x2) /* Regex */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3420 | #define V7_TAG_NOVALUE MAKE_TAG(1, 0x1) /* Sentinel for no value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3421 | #define V7_TAG_MASK MAKE_TAG(1, 0xF) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3422 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3423 | #define _V7_NULL V7_TAG_FOREIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 3424 | #define _V7_UNDEFINED V7_TAG_UNDEFINED |
Marko Mikulicic |
0:c0ecb8bf28eb | 3425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3426 | V7_STATIC_ASSERT(_V7_NULL == V7_NULL, public_V7_NULL_is_wrong); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3427 | V7_STATIC_ASSERT(_V7_UNDEFINED == V7_UNDEFINED, public_V7_UNDEFINED_is_wrong); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3429 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3430 | * Object attributes bitmask |
Marko Mikulicic |
0:c0ecb8bf28eb | 3431 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3432 | typedef unsigned char v7_obj_attr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3433 | #define V7_OBJ_NOT_EXTENSIBLE (1 << 0) /* TODO(lsm): store this in LSB */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3434 | #define V7_OBJ_DENSE_ARRAY (1 << 1) /* TODO(mkm): store in some tag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3435 | #define V7_OBJ_FUNCTION (1 << 2) /* function object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3436 | #define V7_OBJ_OFF_HEAP (1 << 3) /* object not managed by V7 HEAP */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3437 | #define V7_OBJ_HAS_DESTRUCTOR (1 << 4) /* has user data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3438 | #define V7_OBJ_PROXY (1 << 5) /* it's a Proxy object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3440 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3441 | * JavaScript value is either a primitive, or an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3442 | * There are 5 primitive types: Undefined, Null, Boolean, Number, String. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3443 | * Non-primitive type is an Object type. There are several classes of Objects, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3444 | * see description of `struct v7_generic_object` below for more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3445 | * This enumeration combines types and object classes in one enumeration. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3446 | * NOTE(lsm): compile with `-fshort-enums` to reduce sizeof(enum v7_type) to 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3447 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3448 | enum v7_type { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3449 | /* Primitive types */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3450 | V7_TYPE_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3451 | V7_TYPE_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3452 | V7_TYPE_BOOLEAN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3453 | V7_TYPE_NUMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3454 | V7_TYPE_STRING, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3455 | V7_TYPE_FOREIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3456 | V7_TYPE_CFUNCTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3457 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3458 | /* Different classes of Object type */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3459 | V7_TYPE_GENERIC_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3460 | V7_TYPE_BOOLEAN_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3461 | V7_TYPE_STRING_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3462 | V7_TYPE_NUMBER_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3463 | V7_TYPE_FUNCTION_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3464 | V7_TYPE_CFUNCTION_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3465 | V7_TYPE_REGEXP_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3466 | V7_TYPE_ARRAY_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3467 | V7_TYPE_DATE_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3468 | V7_TYPE_ERROR_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3469 | V7_TYPE_MAX_OBJECT_TYPE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3470 | V7_NUM_TYPES |
Marko Mikulicic |
0:c0ecb8bf28eb | 3471 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3473 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3474 | * Call frame type mask: we have a "class hierarchy" of the call frames, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 3475 | * `struct v7_call_frame_base`, and the `type_mask` field represents the exact |
Marko Mikulicic |
0:c0ecb8bf28eb | 3476 | * frame type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3477 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3478 | * Possible values are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3479 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3480 | * - `V7_CALL_FRAME_MASK_PRIVATE | V7_CALL_FRAME_MASK_BCODE`: the most popular |
Marko Mikulicic |
0:c0ecb8bf28eb | 3481 | * frame type: call frame for bcode execution, either top-level code or JS |
Marko Mikulicic |
0:c0ecb8bf28eb | 3482 | * function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3483 | * - `V7_CALL_FRAME_MASK_PRIVATE`: used for `catch` clauses only: the variables |
Marko Mikulicic |
0:c0ecb8bf28eb | 3484 | * we create in `catch` clause should not be visible from the outside of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3485 | * clause, so we have to create a separate scope object for it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3486 | * - `V7_CALL_FRAME_MASK_CFUNC`: call frame for C function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3487 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3488 | typedef uint8_t v7_call_frame_mask_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3489 | #define V7_CALL_FRAME_MASK_BCODE (1 << 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3490 | #define V7_CALL_FRAME_MASK_PRIVATE (1 << 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3491 | #define V7_CALL_FRAME_MASK_CFUNC (1 << 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3493 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3494 | * Base of the call frame; includes the pointer to the previous frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3495 | * and the frame type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3496 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3497 | * In order to save memory, it also contains some bitfields which actually |
Marko Mikulicic |
0:c0ecb8bf28eb | 3498 | * belong to some "sub-structures". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3499 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3500 | * The hierarchy is as follows: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3501 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3502 | * - v7_call_frame_base |
Marko Mikulicic |
0:c0ecb8bf28eb | 3503 | * - v7_call_frame_private |
Marko Mikulicic |
0:c0ecb8bf28eb | 3504 | * - v7_call_frame_bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3505 | * - v7_call_frame_cfunc |
Marko Mikulicic |
0:c0ecb8bf28eb | 3506 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3507 | struct v7_call_frame_base { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3508 | struct v7_call_frame_base *prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3510 | /* See comment for `v7_call_frame_mask_t` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3511 | v7_call_frame_mask_t type_mask : 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3513 | /* Belongs to `struct v7_call_frame_private` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3514 | unsigned int line_no : 16; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3515 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3516 | /* Belongs to `struct v7_call_frame_bcode` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3517 | unsigned is_constructor : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3519 | /* Belongs to `struct v7_call_frame_bcode` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3520 | unsigned int is_thrown : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3521 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3523 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3524 | * "private" call frame, used in `catch` blocks, merely for using a separate |
Marko Mikulicic |
0:c0ecb8bf28eb | 3525 | * scope object there. It is also a "base class" for the bcode call frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3526 | * see `struct v7_call_frame_bcode`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3527 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3528 | * TODO(dfrank): probably implement it differently, so that we can get rid of |
Marko Mikulicic |
0:c0ecb8bf28eb | 3529 | * the separate "private" frames whatsoever (and just include it into struct |
Marko Mikulicic |
0:c0ecb8bf28eb | 3530 | * v7_call_frame_bcode ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3531 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3532 | struct v7_call_frame_private { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3533 | struct v7_call_frame_base base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3534 | size_t stack_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3535 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3536 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3537 | * Current execution scope. Initially, it is equal to the `global_object`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3538 | * and at each function call, it is augmented by the new scope object, which |
Marko Mikulicic |
0:c0ecb8bf28eb | 3539 | * has the previous value as a prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3540 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3541 | val_t scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3542 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3543 | val_t try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3544 | } vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3545 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3546 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3547 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3548 | * "bcode" call frame, augments "private" frame with `bcode` and the position |
Marko Mikulicic |
0:c0ecb8bf28eb | 3549 | * in it, and `this` object. It is the primary frame type, used when executing |
Marko Mikulicic |
0:c0ecb8bf28eb | 3550 | * a bcode script or calling a function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3551 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3552 | struct v7_call_frame_bcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3553 | struct v7_call_frame_private base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3554 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3555 | val_t this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3556 | val_t thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3557 | } vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3558 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3559 | char *bcode_ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3560 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3562 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3563 | * "cfunc" call frame, used when calling cfunctions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3564 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3565 | struct v7_call_frame_cfunc { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3566 | struct v7_call_frame_base base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3567 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3568 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3569 | val_t this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3570 | } vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3572 | v7_cfunction_t *cfunc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3573 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3575 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3576 | * This structure groups together all val_t logical members |
Marko Mikulicic |
0:c0ecb8bf28eb | 3577 | * of struct v7 so that GC and freeze logic can easily access all |
Marko Mikulicic |
0:c0ecb8bf28eb | 3578 | * of them together. This structure must contain only val_t members. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3579 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3580 | struct v7_vals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3581 | val_t global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3582 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3583 | val_t arguments; /* arguments of current call */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3584 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3585 | val_t object_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3586 | val_t array_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3587 | val_t boolean_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3588 | val_t error_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3589 | val_t string_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3590 | val_t regexp_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3591 | val_t number_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3592 | val_t date_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3593 | val_t function_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3594 | val_t proxy_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3595 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3596 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3597 | * temporary register for `OP_STASH` and `OP_UNSTASH` instructions. Valid if |
Marko Mikulicic |
0:c0ecb8bf28eb | 3598 | * `v7->is_stashed` is non-zero |
Marko Mikulicic |
0:c0ecb8bf28eb | 3599 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3600 | val_t stash; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3601 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3602 | val_t error_objects[ERROR_CTOR_MAX]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3604 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3605 | * Value that is being thrown. Valid if `is_thrown` is non-zero (see below) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3606 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3607 | val_t thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3608 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3609 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3610 | * value that is going to be returned. Needed when some `finally` block needs |
Marko Mikulicic |
0:c0ecb8bf28eb | 3611 | * to be executed after `return my_value;` was issued. Used in bcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3612 | * See also `is_returned` below |
Marko Mikulicic |
0:c0ecb8bf28eb | 3613 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3614 | val_t returned_value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3616 | val_t last_name[2]; /* used for error reporting */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3617 | /* most recent OP_CHECK_CALL exceptions, to be thrown by OP_CALL|OP_NEW */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3618 | val_t call_check_ex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3619 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3621 | struct v7 { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3622 | struct v7_vals vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3624 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3625 | * Stack of call frames. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3626 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3627 | * Execution contexts are contained in two chains: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3628 | * - Stack of call frames: to allow returning, throwing, and stack trace |
Marko Mikulicic |
0:c0ecb8bf28eb | 3629 | * generation; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3630 | * - In the lexical scope via their prototype chain (to allow variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 3631 | * lookup), see `struct v7_call_frame_private::scope`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3632 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3633 | * Execution contexts should be allocated on heap, because they might not be |
Marko Mikulicic |
0:c0ecb8bf28eb | 3634 | * on a call stack but still referenced (closures). |
Marko Mikulicic |
0:c0ecb8bf28eb | 3635 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3636 | * New call frame is created every time some top-level code is evaluated, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3637 | * or some code is being `eval`-d, or some function is called, either JS |
Marko Mikulicic |
0:c0ecb8bf28eb | 3638 | * function or C function (although the call frame types are different for |
Marko Mikulicic |
0:c0ecb8bf28eb | 3639 | * JS functions and cfunctions, see `struct v7_call_frame_base` and its |
Marko Mikulicic |
0:c0ecb8bf28eb | 3640 | * sub-structures) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3641 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3642 | * When no code is being evaluated at the moment, `call_stack` is `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3643 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3644 | * See comment for `struct v7_call_frame_base` for some more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3645 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3646 | struct v7_call_frame_base *call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3648 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3649 | * Bcode executes until it reaches `bottom_call_frame`. When some top-level |
Marko Mikulicic |
0:c0ecb8bf28eb | 3650 | * or `eval`-d code starts execution, the `bottom_call_frame` is set to the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3651 | * call frame which was just created for the execution. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3652 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3653 | struct v7_call_frame_base *bottom_call_frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3655 | struct mbuf stack; /* value stack for bcode interpreter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3656 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3657 | struct mbuf owned_strings; /* Sequence of (varint len, char data[]) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3658 | struct mbuf foreign_strings; /* Sequence of (varint len, char *data) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3659 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3660 | struct mbuf tmp_stack; /* Stack of val_t* elements, used as root set */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3661 | int need_gc; /* Set to true to trigger GC when safe */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3663 | struct gc_arena generic_object_arena; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3664 | struct gc_arena function_arena; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3665 | struct gc_arena property_arena; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3666 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 3667 | size_t function_arena_ast_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3668 | size_t bcode_ops_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3669 | size_t bcode_lit_total_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3670 | size_t bcode_lit_deser_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3671 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3672 | struct mbuf owned_values; /* buffer for GC roots owned by C code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3674 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3675 | * Stack of the root bcodes being executed at the moment. Note that when some |
Marko Mikulicic |
0:c0ecb8bf28eb | 3676 | * regular JS function is called inside `eval_bcode()`, the function's bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3677 | * is NOT added here. Buf if some cfunction is called, which in turn calls |
Marko Mikulicic |
0:c0ecb8bf28eb | 3678 | * `b_exec()` (or `b_apply()`) recursively, the new bcode is added to this |
Marko Mikulicic |
0:c0ecb8bf28eb | 3679 | * stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3680 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3681 | struct mbuf act_bcodes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3683 | char error_msg[80]; /* Exception message */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3684 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3685 | struct mbuf json_visited_stack; /* Detecting cycle in to_json */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3687 | /* Parser state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3688 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3689 | struct v7_pstate pstate; /* Parsing state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3690 | enum v7_tok cur_tok; /* Current token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3691 | const char *tok; /* Parsed terminal token (ident, number, string) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3692 | unsigned long tok_len; /* Length of the parsed terminal token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3693 | size_t last_var_node; /* Offset of last var node or function/script node */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3694 | int after_newline; /* True if the cur_tok starts a new line */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3695 | double cur_tok_dbl; /* When tokenizing, parser stores TOK_NUMBER here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3697 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3698 | * Current linenumber. Currently it is used by parser, compiler and bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3699 | * evaluator. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3700 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3701 | * - Parser: it's the last line_no emitted to AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 3702 | * - Compiler: it's the last line_no emitted to bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3703 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3704 | int line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3705 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3707 | /* singleton, pointer because of amalgamation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3708 | struct v7_property *cur_dense_prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3710 | volatile int interrupted; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3711 | #ifdef V7_STACK_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 3712 | void *sp_limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3713 | void *sp_lwm; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3714 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3716 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3717 | /* linked list of v7 contexts, needed by cyg_profile hooks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3718 | struct v7 *next_v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3719 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3720 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3721 | /* linked list of stack tracking contexts */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3722 | struct stack_track_ctx *stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3723 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3724 | int stack_stat[V7_STACK_STATS_CNT]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3725 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3727 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3729 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 3730 | struct mbuf malloc_trace; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3731 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3732 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3733 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3734 | * TODO(imax): remove V7_DISABLE_STR_ALLOC_SEQ knob after 2015/12/01 if there |
Marko Mikulicic |
0:c0ecb8bf28eb | 3735 | * are no issues. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3736 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3737 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3738 | uint16_t gc_next_asn; /* Next sequence number to use. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3739 | uint16_t gc_min_asn; /* Minimal sequence number currently in use. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3740 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3741 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3742 | #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3743 | size_t parser_stack_data_max_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3744 | size_t parser_stack_ret_max_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3745 | size_t parser_stack_data_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3746 | size_t parser_stack_ret_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3747 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3749 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 3750 | FILE *freeze_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3751 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3753 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3754 | * true if exception is currently being created. Needed to avoid recursive |
Marko Mikulicic |
0:c0ecb8bf28eb | 3755 | * exception creation |
Marko Mikulicic |
0:c0ecb8bf28eb | 3756 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3757 | unsigned int creating_exception : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3758 | /* while true, GC is inhibited */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3759 | unsigned int inhibit_gc : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3760 | /* true if `thrown_error` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3761 | unsigned int is_thrown : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3762 | /* true if `returned_value` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3763 | unsigned int is_returned : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3764 | /* true if a finally block is executing while breaking */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3765 | unsigned int is_breaking : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3766 | /* true when a continue OP is executed, reset by `OP_JMP_IF_CONTINUE` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3767 | unsigned int is_continuing : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3768 | /* true if some value is currently stashed (`v7->vals.stash`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3769 | unsigned int is_stashed : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3770 | /* true if last emitted statement does not affect data stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3771 | unsigned int is_stack_neutral : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3772 | /* true if precompiling; affects compiler bcode choices */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3773 | unsigned int is_precompiling : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3775 | enum opcode last_ops[2]; /* trace of last ops, used for error reporting */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3776 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3778 | struct v7_property { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3779 | struct v7_property * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3780 | next; /* Linkage in struct v7_generic_object::properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3781 | v7_prop_attr_t attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3782 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3783 | entity_id_t entity_id; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3784 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3785 | val_t name; /* Property name (a string) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3786 | val_t value; /* Property value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3787 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3789 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3790 | * "base object": structure which is shared between objects and functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3791 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3792 | struct v7_object { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3793 | /* First HIDDEN property in a chain is an internal object value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3794 | struct v7_property *properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3795 | v7_obj_attr_t attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3796 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3797 | entity_id_part_t entity_id_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3798 | entity_id_part_t entity_id_spec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3799 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3800 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3802 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3803 | * An object is an unordered collection of properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3804 | * A function stored in a property of an object is called a method. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3805 | * A property has a name, a value, and set of attributes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3806 | * Attributes are: ReadOnly, DontEnum, DontDelete, Internal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3807 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3808 | * A constructor is a function that creates and initializes objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3809 | * Each constructor has an associated prototype object that is used for |
Marko Mikulicic |
0:c0ecb8bf28eb | 3810 | * inheritance and shared properties. When a constructor creates an object, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3811 | * the new object references the constructor’s prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3812 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3813 | * Objects could be a "generic objects" which is a collection of properties, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3814 | * or a "typed object" which also hold an internal value like String or Number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3815 | * Those values are implicit, unnamed properties of the respective types, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3816 | * and can be coerced into primitive types by calling a respective constructor |
Marko Mikulicic |
0:c0ecb8bf28eb | 3817 | * as a function: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3818 | * var a = new Number(123); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3819 | * typeof(a) == 'object'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3820 | * typeof(Number(a)) == 'number'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3821 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3822 | struct v7_generic_object { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3823 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3824 | * This has to be the first field so that objects can be managed by the GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3825 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3826 | struct v7_object base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3827 | struct v7_object *prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3828 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3830 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3831 | * Variables are function-scoped and are hoisted. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3832 | * Lexical scoping & closures: each function has a chain of scopes, defined |
Marko Mikulicic |
0:c0ecb8bf28eb | 3833 | * by the lexicographic order of function definitions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3834 | * Scope is different from the execution context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3835 | * Execution context carries "variable object" which is variable/value |
Marko Mikulicic |
0:c0ecb8bf28eb | 3836 | * mapping for all variables defined in a function, and `this` object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3837 | * If function is not called as a method, then `this` is a global object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3838 | * Otherwise, `this` is an object that contains called method. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3839 | * New execution context is created each time a function call is performed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3840 | * Passing arguments through recursion is done using execution context, e.g. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3841 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3842 | * var factorial = function(num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3843 | * return num < 2 ? 1 : num * factorial(num - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3844 | * }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3845 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3846 | * Here, recursion calls the same function `factorial` several times. Execution |
Marko Mikulicic |
0:c0ecb8bf28eb | 3847 | * contexts for each call form a stack. Each context has different variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 3848 | * object, `vars`, with different values of `num`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3849 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3850 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3851 | struct v7_js_function { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3852 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3853 | * Functions are objects. This has to be the first field so that function |
Marko Mikulicic |
0:c0ecb8bf28eb | 3854 | * objects can be managed by the GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3855 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3856 | struct v7_object base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3857 | struct v7_generic_object *scope; /* lexical scope of the closure */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3859 | /* bytecode, might be shared between functions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3860 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3861 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3863 | struct v7_regexp { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3864 | val_t regexp_string; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3865 | struct slre_prog *compiled_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3866 | long lastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3867 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3869 | /* Vector, describes some memory location pointed by `p` with length `len` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3870 | struct v7_vec { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3871 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3872 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3873 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3875 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3876 | * Constant vector, describes some const memory location pointed by `p` with |
Marko Mikulicic |
0:c0ecb8bf28eb | 3877 | * length `len` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3878 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3879 | struct v7_vec_const { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3880 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3881 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3882 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3884 | #define V7_VEC(str) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3885 | { (str), sizeof(str) - 1 } |
Marko Mikulicic |
0:c0ecb8bf28eb | 3886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3887 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3888 | * Returns current execution scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3889 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3890 | * See comment for `struct v7_call_frame_private::vals::scope` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3891 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3892 | V7_PRIVATE v7_val_t get_scope(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3894 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3895 | * Returns 1 if currently executing bcode in the "strict mode", 0 otherwise |
Marko Mikulicic |
0:c0ecb8bf28eb | 3896 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3897 | V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3899 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3900 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 3901 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3903 | #endif /* CS_V7_SRC_CORE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3904 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 3905 | #line 1 "v7/src/primitive_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 3906 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3907 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3908 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 3909 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 3910 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3912 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3913 | * === Primitives |
Marko Mikulicic |
0:c0ecb8bf28eb | 3914 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3915 | * All primitive values but strings. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3916 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3917 | * "foreign" values are also here, see `v7_mk_foreign()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3918 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3920 | #ifndef CS_V7_SRC_PRIMITIVE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3921 | #define CS_V7_SRC_PRIMITIVE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3923 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3925 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3926 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3927 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3929 | /* Make numeric primitive value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3930 | NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double num); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3931 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3932 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3933 | * Returns number value stored in `v7_val_t` as `double`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3934 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3935 | * Returns NaN for non-numbers. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3936 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3937 | NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3939 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3940 | * Returns number value stored in `v7_val_t` as `int`. If the number value is |
Marko Mikulicic |
0:c0ecb8bf28eb | 3941 | * not an integer, the fraction part will be discarded. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3942 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3943 | * If the given value is a non-number, or NaN, the result is undefined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3944 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3945 | NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3946 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3947 | /* Returns true if given value is a primitive number value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3948 | int v7_is_number(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3950 | /* Make boolean primitive value (either `true` or `false`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3951 | NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int is_true); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3953 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3954 | * Returns boolean stored in `v7_val_t`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3955 | * 0 for `false` or non-boolean, non-0 for `true` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3956 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3957 | NOINSTR int v7_get_bool(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3959 | /* Returns true if given value is a primitive boolean value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3960 | int v7_is_boolean(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3961 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3962 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3963 | * Make `null` primitive value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3964 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3965 | * NOTE: this function is deprecated and will be removed in future releases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3966 | * Use `V7_NULL` instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3967 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3968 | NOINSTR v7_val_t v7_mk_null(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3970 | /* Returns true if given value is a primitive `null` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3971 | int v7_is_null(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3972 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3973 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3974 | * Make `undefined` primitive value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3975 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3976 | * NOTE: this function is deprecated and will be removed in future releases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3977 | * Use `V7_UNDEFINED` instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3978 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3979 | NOINSTR v7_val_t v7_mk_undefined(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3981 | /* Returns true if given value is a primitive `undefined` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3982 | int v7_is_undefined(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3984 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3985 | * Make JavaScript value that holds C/C++ `void *` pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3986 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3987 | * A foreign value is completely opaque and JS code cannot do anything useful |
Marko Mikulicic |
0:c0ecb8bf28eb | 3988 | * with it except holding it in properties and passing it around. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3989 | * It behaves like a sealed object with no properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3990 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3991 | * NOTE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3992 | * Only valid pointers (as defined by each supported architecture) will fully |
Marko Mikulicic |
0:c0ecb8bf28eb | 3993 | * preserved. In particular, all supported 64-bit architectures (x86_64, ARM-64) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3994 | * actually define a 48-bit virtual address space. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3995 | * Foreign values will be sign-extended as required, i.e creating a foreign |
Marko Mikulicic |
0:c0ecb8bf28eb | 3996 | * value of something like `(void *) -1` will work as expected. This is |
Marko Mikulicic |
0:c0ecb8bf28eb | 3997 | * important because in some 64-bit OSs (e.g. Solaris) the user stack grows |
Marko Mikulicic |
0:c0ecb8bf28eb | 3998 | * downwards from the end of the address space. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3999 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4000 | * If you need to store exactly sizeof(void*) bytes of raw data where |
Marko Mikulicic |
0:c0ecb8bf28eb | 4001 | * `sizeof(void*)` >= 8, please use byte arrays instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4002 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4003 | NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *ptr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4005 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4006 | * Returns `void *` pointer stored in `v7_val_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4007 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4008 | * Returns NULL if the value is not a foreign pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4009 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4010 | NOINSTR void *v7_get_ptr(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4012 | /* Returns true if given value holds `void *` pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4013 | int v7_is_foreign(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4015 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4016 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4017 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4018 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4019 | #endif /* CS_V7_SRC_PRIMITIVE_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4020 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4021 | #line 1 "v7/src/primitive.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4022 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4023 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4024 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4025 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4026 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4027 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4028 | #ifndef CS_V7_SRC_PRIMITIVE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4029 | #define CS_V7_SRC_PRIMITIVE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4031 | /* Amalgamated: #include "v7/src/primitive_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4033 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4035 | /* Returns true if given value is a number, not NaN and not Infinity. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4036 | V7_PRIVATE int is_finite(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4038 | V7_PRIVATE val_t pointer_to_value(void *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4039 | V7_PRIVATE void *get_ptr(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4040 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4041 | #endif /* CS_V7_SRC_PRIMITIVE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4042 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4043 | #line 1 "v7/src/string_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4044 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4045 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4046 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4047 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4048 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4050 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4051 | * === Strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 4052 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4054 | #ifndef CS_V7_SRC_STRING_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4055 | #define CS_V7_SRC_STRING_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4057 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4059 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4060 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4061 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4063 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4064 | * Creates a string primitive value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4065 | * `str` must point to the utf8 string of length `len`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4066 | * If `len` is ~0, `str` is assumed to be NUL-terminated and `strlen(str)` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4067 | * used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4068 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4069 | * If `copy` is non-zero, the string data is copied and owned by the GC. The |
Marko Mikulicic |
0:c0ecb8bf28eb | 4070 | * caller can free the string data afterwards. Otherwise (`copy` is zero), the |
Marko Mikulicic |
0:c0ecb8bf28eb | 4071 | * caller owns the string data, and is responsible for not freeing it while it |
Marko Mikulicic |
0:c0ecb8bf28eb | 4072 | * is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4073 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4074 | v7_val_t v7_mk_string(struct v7 *v7, const char *str, size_t len, int copy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4076 | /* Returns true if given value is a primitive string value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4077 | int v7_is_string(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4079 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4080 | * Returns a pointer to the string stored in `v7_val_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4081 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4082 | * String length returned in `len`, which is allowed to be NULL. Returns NULL |
Marko Mikulicic |
0:c0ecb8bf28eb | 4083 | * if the value is not a string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4084 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4085 | * JS strings can contain embedded NUL chars and may or may not be NUL |
Marko Mikulicic |
0:c0ecb8bf28eb | 4086 | * terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4087 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4088 | * CAUTION: creating new JavaScript object, array, or string may kick in a |
Marko Mikulicic |
0:c0ecb8bf28eb | 4089 | * garbage collector, which in turn may relocate string data and invalidate |
Marko Mikulicic |
0:c0ecb8bf28eb | 4090 | * pointer returned by `v7_get_string()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4091 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4092 | * Short JS strings are embedded inside the `v7_val_t` value itself. This is why |
Marko Mikulicic |
0:c0ecb8bf28eb | 4093 | * a pointer to a `v7_val_t` is required. It also means that the string data |
Marko Mikulicic |
0:c0ecb8bf28eb | 4094 | * will become invalid once that `v7_val_t` value goes out of scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4095 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4096 | const char *v7_get_string(struct v7 *v7, v7_val_t *v, size_t *len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4098 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4099 | * Returns a pointer to the string stored in `v7_val_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4100 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4101 | * Returns NULL if the value is not a string or if the string is not compatible |
Marko Mikulicic |
0:c0ecb8bf28eb | 4102 | * with a C string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4103 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4104 | * C compatible strings contain exactly one NUL char, in terminal position. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4105 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4106 | * All strings owned by the V7 engine (see `v7_mk_string()`) are guaranteed to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4107 | * be NUL terminated. Out of these, those that don't include embedded NUL chars |
Marko Mikulicic |
0:c0ecb8bf28eb | 4108 | * are guaranteed to be C compatible. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4109 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4110 | const char *v7_get_cstring(struct v7 *v7, v7_val_t *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4112 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4113 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4114 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4115 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4116 | #endif /* CS_V7_SRC_STRING_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4117 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4118 | #line 1 "v7/src/string.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4119 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4120 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4121 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4122 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4123 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4125 | #ifndef CS_V7_SRC_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4126 | #define CS_V7_SRC_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4128 | /* Amalgamated: #include "v7/src/string_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4129 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4130 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4132 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4133 | * Size of the extra space for strings mbuf that is needed to avoid frequent |
Marko Mikulicic |
0:c0ecb8bf28eb | 4134 | * reallocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 4135 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4136 | #define _V7_STRING_BUF_RESERVE 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 4137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4138 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4139 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4140 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4142 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4143 | V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, v7_val_t s, v7_val_t at, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4144 | double *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4145 | V7_PRIVATE int s_cmp(struct v7 *, val_t a, val_t b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4146 | V7_PRIVATE val_t s_concat(struct v7 *, val_t, val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4147 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4148 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4149 | * Convert a C string to to an unsigned integer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4150 | * `ok` will be set to true if the string conforms to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4151 | * an unsigned long. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4152 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4153 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4154 | V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4155 | unsigned long *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4157 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4158 | * Convert a V7 string to to an unsigned integer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4159 | * `ok` will be set to true if the string conforms to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4160 | * an unsigned long. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4161 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4162 | * Use it if only you need strong conformity of the value to an integer; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4163 | * otherwise, use `to_long()` or `to_number_v()` instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4164 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4165 | V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4167 | enum embstr_flags { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4168 | EMBSTR_ZERO_TERM = (1 << 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 4169 | EMBSTR_UNESCAPE = (1 << 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 4170 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4172 | V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4173 | size_t len, uint8_t /*enum embstr_flags*/ flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4175 | V7_PRIVATE size_t unescape(const char *s, size_t len, char *to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4177 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4178 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4179 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4180 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4181 | #endif /* CS_V7_SRC_STRING_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4182 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4183 | #line 1 "v7/src/exceptions_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4184 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4185 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4186 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4187 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4188 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4189 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4190 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4191 | * === Exceptions |
Marko Mikulicic |
0:c0ecb8bf28eb | 4192 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4194 | #ifndef CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4195 | #define CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4197 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4199 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4200 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4201 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4203 | /* Throw an exception with an already existing value. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4204 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4205 | enum v7_err v7_throw(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4207 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4208 | * Throw an exception with given formatted message. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4209 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4210 | * Pass "Error" as typ for a generic error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4211 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4212 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4213 | enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, ...); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4214 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4215 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4216 | * Rethrow the currently thrown object. In fact, it just returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 4217 | * V7_EXEC_EXCEPTION. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4218 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4219 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4220 | enum v7_err v7_rethrow(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4222 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4223 | * Returns the value that is being thrown at the moment, or `undefined` if |
Marko Mikulicic |
0:c0ecb8bf28eb | 4224 | * nothing is being thrown. If `is_thrown` is not `NULL`, it will be set |
Marko Mikulicic |
0:c0ecb8bf28eb | 4225 | * to either 0 or 1, depending on whether something is thrown at the moment. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4226 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4227 | v7_val_t v7_get_thrown_value(struct v7 *v7, unsigned char *is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4229 | /* Clears currently thrown value, if any. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4230 | void v7_clear_thrown_value(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4232 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4233 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4234 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4236 | #endif /* CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4237 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4238 | #line 1 "v7/src/exceptions.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4239 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4240 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4241 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4242 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4243 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4244 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4245 | #ifndef CS_V7_SRC_EXCEPTIONS_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4246 | #define CS_V7_SRC_EXCEPTIONS_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4248 | /* Amalgamated: #include "v7/src/exceptions_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4249 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4250 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4252 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4253 | * Try to perform some arbitrary call, and if the result is other than `V7_OK`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4254 | * "throws" an error with `V7_THROW()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4255 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4256 | #define V7_TRY2(call, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4257 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4258 | enum v7_err _e = call; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4259 | V7_CHECK2(_e == V7_OK, _e, clean_label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4260 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4262 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4263 | * Sets return value to the provided one, and `goto`s `clean`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4264 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4265 | * For this to work, you should have local `enum v7_err rcode` variable, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4266 | * and a `clean` label. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4267 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4268 | #define V7_THROW2(err_code, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4269 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4270 | (void) v7; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4271 | rcode = (err_code); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4272 | assert(rcode != V7_OK); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4273 | assert(!v7_is_undefined(v7->vals.thrown_error) && v7->is_thrown); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4274 | goto clean_label; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4275 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4277 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4278 | * Checks provided condition `cond`, and if it's false, then "throws" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4279 | * provided `err_code` (see `V7_THROW()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4280 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4281 | #define V7_CHECK2(cond, err_code, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4282 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4283 | if (!(cond)) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4284 | V7_THROW2(err_code, clean_label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4285 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4286 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4288 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4289 | * Checks provided condition `cond`, and if it's false, then "throws" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4290 | * internal error |
Marko Mikulicic |
0:c0ecb8bf28eb | 4291 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4292 | * TODO(dfrank): it would be good to have formatted string: then, we can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4293 | * specify file and line. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4294 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4295 | #define V7_CHECK_INTERNAL2(cond, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4296 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4297 | if (!(cond)) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4298 | enum v7_err __rcode = v7_throwf(v7, "Error", "Internal error"); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4299 | (void) __rcode; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4300 | V7_THROW2(V7_INTERNAL_ERROR, clean_label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4301 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4302 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4303 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4304 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4305 | * Shortcuts for the macros above, but they assume the clean label `clean`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4306 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4308 | #define V7_TRY(call) V7_TRY2(call, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4309 | #define V7_THROW(err_code) V7_THROW2(err_code, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4310 | #define V7_CHECK(cond, err_code) V7_CHECK2(cond, err_code, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4311 | #define V7_CHECK_INTERNAL(cond) V7_CHECK_INTERNAL2(cond, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4312 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4313 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4314 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4315 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4317 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4318 | * At the moment, most of the exception-related functions are public, and are |
Marko Mikulicic |
0:c0ecb8bf28eb | 4319 | * declared in `exceptions_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4320 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4322 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4323 | * Create an instance of the exception with type `typ` (see `TYPE_ERROR`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4324 | * `SYNTAX_ERROR`, etc), and message `msg`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4325 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4326 | V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4327 | const char *msg, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4328 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4329 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4330 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4331 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4333 | #endif /* CS_V7_SRC_EXCEPTIONS_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4334 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4335 | #line 1 "v7/src/object.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4336 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4337 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4338 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4339 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4340 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4342 | #ifndef CS_V7_SRC_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4343 | #define CS_V7_SRC_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4345 | /* Amalgamated: #include "v7/src/object_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4347 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4348 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4350 | V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4351 | V7_PRIVATE val_t v7_object_to_value(struct v7_object *o); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4352 | V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4354 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4355 | * Returns pointer to the struct representing an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4356 | * Given value must be an object (the caller can verify it |
Marko Mikulicic |
0:c0ecb8bf28eb | 4357 | * by calling `v7_is_object()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4358 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4359 | V7_PRIVATE struct v7_object *get_object_struct(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4361 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4362 | * Return true if given value is a JavaScript object (will return |
Marko Mikulicic |
0:c0ecb8bf28eb | 4363 | * false for function) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4364 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4365 | V7_PRIVATE int v7_is_generic_object(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4366 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4367 | V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4369 | V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4370 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4371 | size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4372 | v7_prop_attr_t attrs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4374 | V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4375 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4376 | size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4378 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4379 | * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated |
Marko Mikulicic |
0:c0ecb8bf28eb | 4380 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4381 | * Returns a pointer to the property structure, given an object and a name of |
Marko Mikulicic |
0:c0ecb8bf28eb | 4382 | * the property as a pointer to string buffer and length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4383 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4384 | * See also `v7_get_property_v` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4385 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4386 | V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4387 | const char *name, size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4389 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4390 | * Just like `v7_get_property`, but takes name as a `v7_val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4391 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4392 | V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4393 | v7_val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4394 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4396 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4397 | V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4398 | v7_val_t name, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4400 | V7_PRIVATE void v7_destroy_property(struct v7_property **p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4402 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4403 | V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4404 | val_t obj, val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4406 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4407 | * Like `set_property`, but takes property name as a `val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4408 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4409 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4410 | V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4411 | val_t val, struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4413 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4414 | * Like JavaScript assignment: set a property with given `name` + `len` at |
Marko Mikulicic |
0:c0ecb8bf28eb | 4415 | * the object `obj` to value `val`. Returns a property through the `res` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4416 | * (which may be `NULL` if return value is not required) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4417 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4418 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4419 | V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4420 | size_t len, v7_val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4421 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4422 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4423 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4424 | * Like `def_property()`, but takes property name as a `val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4425 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4426 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4427 | V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4428 | v7_prop_attr_desc_t attrs_desc, val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4429 | uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4430 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4432 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4433 | * Define object property, similar to JavaScript `Object.defineProperty()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4434 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4435 | * Just like public `v7_def()`, but returns `enum v7_err`, and therefore can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4436 | * throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4437 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4438 | * Additionally, takes param `as_assign`: if it is non-zero, it behaves |
Marko Mikulicic |
0:c0ecb8bf28eb | 4439 | * similarly to plain JavaScript assignment in terms of some exception-related |
Marko Mikulicic |
0:c0ecb8bf28eb | 4440 | * corner cases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4441 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4442 | * `res` may be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4443 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4444 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4445 | V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4446 | size_t len, v7_prop_attr_desc_t attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4447 | v7_val_t val, uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4448 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4450 | V7_PRIVATE int set_method(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4451 | v7_cfunction_t *func, int num_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4453 | V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4454 | v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4456 | /* Return address of property value or NULL if the passed property is NULL */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4457 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4458 | V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4459 | struct v7_property *p, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4461 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 4462 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4463 | * Additional context for property iteration of a proxied object, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 4464 | * `v7_next_prop()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4465 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4466 | struct prop_iter_proxy_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4467 | /* Proxy target object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4468 | v7_val_t target_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4469 | /* Proxy handler object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4470 | v7_val_t handler_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4472 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4473 | * array returned by the `ownKeys` callback, valid if only `has_own_keys` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4474 | * set |
Marko Mikulicic |
0:c0ecb8bf28eb | 4475 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4476 | v7_val_t own_keys; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4477 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4478 | * callback to get property descriptor, one of these: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4479 | * - a JS or cfunction `getOwnPropertyDescriptor` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4480 | * (if `has_get_own_prop_desc_C` is not set); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4481 | * - a C callback `v7_get_own_prop_desc_cb_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4482 | * (if `has_get_own_prop_desc_C` is set); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4483 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4484 | v7_val_t get_own_prop_desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4486 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4487 | * if `has_own_keys` is set, `own_key_idx` represents next index in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 4488 | * `own_keys` array |
Marko Mikulicic |
0:c0ecb8bf28eb | 4489 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4490 | unsigned own_key_idx : 29; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4492 | /* if set, `own_keys` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4493 | unsigned has_own_keys : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4494 | /* if set, `get_own_prop_desc` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4495 | unsigned has_get_own_prop_desc : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4496 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4497 | * if set, `get_own_prop_desc` is a C callback `has_get_own_prop_desc_C`, not |
Marko Mikulicic |
0:c0ecb8bf28eb | 4498 | * a JS callback |
Marko Mikulicic |
0:c0ecb8bf28eb | 4499 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4500 | unsigned has_get_own_prop_desc_C : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4501 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4502 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4503 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4504 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4505 | * Like public function `v7_init_prop_iter_ctx()`, but it takes additional |
Marko Mikulicic |
0:c0ecb8bf28eb | 4506 | * argument `proxy_transp`; if it is zero, and the given `obj` is a Proxy, it |
Marko Mikulicic |
0:c0ecb8bf28eb | 4507 | * will iterate the properties of the proxy itself, not the Proxy's target. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4508 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4509 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4510 | V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4511 | int proxy_transp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4512 | struct prop_iter_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4513 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4514 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4515 | V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4516 | v7_val_t *name, v7_val_t *value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4517 | v7_prop_attr_t *attrs, int *ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4519 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4520 | * Set new prototype `proto` for the given object `obj`. Returns `0` at |
Marko Mikulicic |
0:c0ecb8bf28eb | 4521 | * success, `-1` at failure (it may fail if given `obj` is a function object: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4522 | * it's impossible to change function object's prototype) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4523 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4524 | V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4525 | struct v7_object *proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4527 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4528 | * Given a pointer to the object structure, returns a |
Marko Mikulicic |
0:c0ecb8bf28eb | 4529 | * pointer to the prototype object, or `NULL` if there is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4530 | * no prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4531 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4532 | V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4533 | struct v7_object *obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4535 | V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4537 | /* Get the property holding user data and destructor, or NULL */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4538 | V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4540 | #endif /* CS_V7_SRC_OBJECT_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4541 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4542 | #line 1 "v7/src/exec_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4543 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4544 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4545 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4546 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4547 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4548 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4549 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4550 | * === Execution of JavaScript code |
Marko Mikulicic |
0:c0ecb8bf28eb | 4551 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4552 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4553 | #ifndef CS_V7_SRC_EXEC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4554 | #define CS_V7_SRC_EXEC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4556 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4557 | |
Marko Mikulicic |
2:7762b98d31c7 | 4558 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 4559 | extern "C" { |
Marko Mikulicic |
2:7762b98d31c7 | 4560 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 4561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4562 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4563 | * Execute JavaScript `js_code`. The result of evaluation is stored in |
Marko Mikulicic |
0:c0ecb8bf28eb | 4564 | * the `result` variable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4565 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4566 | * Return: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4567 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4568 | * - V7_OK on success. `result` contains the result of execution. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4569 | * - V7_SYNTAX_ERROR if `js_code` in not a valid code. `result` is undefined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4570 | * - V7_EXEC_EXCEPTION if `js_code` threw an exception. `result` stores |
Marko Mikulicic |
0:c0ecb8bf28eb | 4571 | * an exception object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4572 | * - V7_AST_TOO_LARGE if `js_code` contains an AST segment longer than 16 bit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4573 | * `result` is undefined. To avoid this error, build V7 with V7_LARGE_AST. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4574 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4575 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4576 | enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4578 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4579 | * Options for `v7_exec_opt()`. To get default options, like `v7_exec()` uses, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4580 | * just zero out this struct. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4581 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4582 | struct v7_exec_opts { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4583 | /* Filename, used for stack traces only */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4584 | const char *filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4586 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4587 | * Object to be used as `this`. Note: when it is zeroed out, i.e. it's a |
Marko Mikulicic |
0:c0ecb8bf28eb | 4588 | * number `0`, the `undefined` value is assumed. It means that it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 4589 | * impossible to actually use the number `0` as `this` object, but it makes |
Marko Mikulicic |
0:c0ecb8bf28eb | 4590 | * little sense anyway. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4591 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4592 | v7_val_t this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4594 | /* Whether the given `js_code` should be interpreted as JSON, not JS code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4595 | unsigned is_json : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4596 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4597 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4598 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4599 | * Customizable version of `v7_exec()`: allows to specify various options, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 4600 | * `struct v7_exec_opts`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4601 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4602 | enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4603 | const struct v7_exec_opts *opts, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4605 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4606 | * Same as `v7_exec()`, but loads source code from `path` file. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4607 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4608 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4609 | enum v7_err v7_exec_file(struct v7 *v7, const char *path, v7_val_t *result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4611 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4612 | * Parse `str` and store corresponding JavaScript object in `res` variable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4613 | * String `str` should be '\0'-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4614 | * Return value and semantic is the same as for `v7_exec()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4615 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4616 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4617 | enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4618 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4619 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4620 | * Same as `v7_parse_json()`, but loads JSON string from `path`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4621 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4622 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4623 | enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4624 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4625 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4627 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4628 | * Compile JavaScript code `js_code` into the byte code and write generated |
Marko Mikulicic |
0:c0ecb8bf28eb | 4629 | * byte code into opened file stream `fp`. If `generate_binary_output` is 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4630 | * then generated byte code is in human-readable text format. Otherwise, it is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4631 | * in the binary format, suitable for execution by V7 instance. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4632 | * NOTE: `fp` must be a valid, opened, writable file stream. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4633 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4634 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4635 | enum v7_err v7_compile(const char *js_code, int generate_binary_output, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4636 | int use_bcode, FILE *fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4638 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4640 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4641 | * Call function `func` with arguments `args`, using `this_obj` as `this`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4642 | * `args` should be an array containing arguments or `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4643 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4644 | * `res` can be `NULL` if return value is not required. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4645 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4646 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4647 | enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4648 | v7_val_t args, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4649 | |
Marko Mikulicic |
2:7762b98d31c7 | 4650 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 4651 | } |
Marko Mikulicic |
2:7762b98d31c7 | 4652 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 4653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4654 | #endif /* CS_V7_SRC_EXEC_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4655 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4656 | #line 1 "v7/src/exec.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4657 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4658 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4659 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4660 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4661 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4663 | #ifndef CS_V7_SRC_EXEC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4664 | #define CS_V7_SRC_EXEC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4666 | /* Amalgamated: #include "v7/src/exec_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4668 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4670 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4672 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4673 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4674 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4675 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4676 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4677 | * At the moment, all exec-related functions are public, and are declared in |
Marko Mikulicic |
0:c0ecb8bf28eb | 4678 | * `exec_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4679 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4680 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4681 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4682 | enum v7_err _v7_compile(const char *js_code, size_t js_code_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4683 | int generate_binary_output, int use_bcode, FILE *fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4684 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4685 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4686 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4687 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4689 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4690 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4691 | #endif /* CS_V7_SRC_EXEC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4692 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4693 | #line 1 "v7/src/array_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4694 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4695 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4696 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4697 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4698 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4700 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4701 | * === Arrays |
Marko Mikulicic |
0:c0ecb8bf28eb | 4702 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4704 | #ifndef CS_V7_SRC_ARRAY_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4705 | #define CS_V7_SRC_ARRAY_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4707 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4708 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4709 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4710 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4711 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4713 | /* Make an empty array object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4714 | v7_val_t v7_mk_array(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4716 | /* Returns true if given value is an array object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4717 | int v7_is_array(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4719 | /* Returns length on an array. If `arr` is not an array, 0 is returned. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4720 | unsigned long v7_array_length(struct v7 *v7, v7_val_t arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4722 | /* Insert value `v` in array `arr` at the end of the array. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4723 | int v7_array_push(struct v7 *, v7_val_t arr, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4725 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4726 | * Like `v7_array_push()`, but "returns" value through the `res` pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4727 | * argument. `res` is allowed to be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4728 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4729 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 4730 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4731 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4732 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4733 | enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4734 | int *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4736 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4737 | * Return array member at index `index`. If `index` is out of bounds, undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 4738 | * is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4739 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4740 | v7_val_t v7_array_get(struct v7 *, v7_val_t arr, unsigned long index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4741 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4742 | /* Insert value `v` into `arr` at index `index`. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4743 | int v7_array_set(struct v7 *v7, v7_val_t arr, unsigned long index, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4745 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4746 | * Like `v7_array_set()`, but "returns" value through the `res` pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4747 | * argument. `res` is allowed to be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4748 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4749 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 4750 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4751 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4752 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4753 | enum v7_err v7_array_set_throwing(struct v7 *v7, v7_val_t arr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4754 | unsigned long index, v7_val_t v, int *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4756 | /* Delete value in array `arr` at index `index`, if it exists. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4757 | void v7_array_del(struct v7 *v7, v7_val_t arr, unsigned long index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4758 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4759 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4760 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4761 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4762 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4763 | #endif /* CS_V7_SRC_ARRAY_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4764 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4765 | #line 1 "v7/src/array.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4766 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4767 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4768 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4769 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4770 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4771 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4772 | #ifndef CS_V7_SRC_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4773 | #define CS_V7_SRC_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4775 | /* Amalgamated: #include "v7/src/array_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4777 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4779 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4780 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4781 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4783 | V7_PRIVATE v7_val_t v7_mk_dense_array(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4784 | V7_PRIVATE val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 4785 | v7_array_get2(struct v7 *v7, v7_val_t arr, unsigned long index, int *has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4786 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4787 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4788 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4789 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4790 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4791 | #endif /* CS_V7_SRC_ARRAY_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4792 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4793 | #line 1 "v7/src/conversion_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4794 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4795 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4796 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4797 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4798 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4799 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4800 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4801 | * === Conversion |
Marko Mikulicic |
0:c0ecb8bf28eb | 4802 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4804 | #ifndef CS_V7_SRC_CONVERSION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4805 | #define CS_V7_SRC_CONVERSION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4806 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4807 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4809 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4810 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4811 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4813 | /* Stringify mode, see `v7_stringify()` and `v7_stringify_throwing()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4814 | enum v7_stringify_mode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4815 | V7_STRINGIFY_DEFAULT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4816 | V7_STRINGIFY_JSON, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4817 | V7_STRINGIFY_DEBUG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4818 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4820 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4821 | * Generate string representation of the JavaScript value `val` into a buffer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4822 | * `buf`, `len`. If `len` is too small to hold a generated string, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4823 | * `v7_stringify()` allocates required memory. In that case, it is caller's |
Marko Mikulicic |
0:c0ecb8bf28eb | 4824 | * responsibility to free the allocated buffer. Generated string is guaranteed |
Marko Mikulicic |
0:c0ecb8bf28eb | 4825 | * to be 0-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4826 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4827 | * Available stringification modes are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4828 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4829 | * - `V7_STRINGIFY_DEFAULT`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4830 | * Convert JS value to string, using common JavaScript semantics: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4831 | * - If value is an object: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4832 | * - call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4833 | * - If `toString()` returned non-primitive value, call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4834 | * - If `valueOf()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4835 | * - Now we have a primitive, and if it's not a string, then stringify it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4836 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4837 | * - `V7_STRINGIFY_JSON`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4838 | * Generate JSON output |
Marko Mikulicic |
0:c0ecb8bf28eb | 4839 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4840 | * - `V7_STRINGIFY_DEBUG`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4841 | * Mostly like JSON, but will not omit non-JSON objects like functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4842 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4843 | * Example code: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4844 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4845 | * char buf[100], *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4846 | * p = v7_stringify(v7, obj, buf, sizeof(buf), V7_STRINGIFY_DEFAULT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4847 | * printf("JSON string: [%s]\n", p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4848 | * if (p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4849 | * free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4850 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4851 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4852 | char *v7_stringify(struct v7 *v7, v7_val_t v, char *buf, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4853 | enum v7_stringify_mode mode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4855 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4856 | * Like `v7_stringify()`, but "returns" value through the `res` pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4857 | * argument. `res` must not be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4858 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4859 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 4860 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4861 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4862 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4863 | enum v7_err v7_stringify_throwing(struct v7 *v7, v7_val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4864 | size_t size, enum v7_stringify_mode mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4865 | char **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4867 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4868 | * A shortcut for `v7_stringify()` with `V7_STRINGIFY_JSON` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4869 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4870 | #define v7_to_json(a, b, c, d) v7_stringify(a, b, c, d, V7_STRINGIFY_JSON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4872 | /* Returns true if given value evaluates to true, as in `if (v)` statement. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4873 | int v7_is_truthy(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4875 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4876 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4877 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4879 | #endif /* CS_V7_SRC_CONVERSION_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4880 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4881 | #line 1 "v7/src/conversion.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4882 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4883 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4884 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4885 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4886 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4888 | #ifndef CS_V7_SRC_CONVERSION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4889 | #define CS_V7_SRC_CONVERSION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4890 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4891 | /* Amalgamated: #include "v7/src/conversion_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4893 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4894 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4895 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4896 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4897 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4899 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4900 | * Conversion API |
Marko Mikulicic |
0:c0ecb8bf28eb | 4901 | * ============== |
Marko Mikulicic |
0:c0ecb8bf28eb | 4902 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4903 | * - If you need to convert any JS value to string using common JavaScript |
Marko Mikulicic |
0:c0ecb8bf28eb | 4904 | * semantics, use `to_string()`, which can convert to both `v7_val_t` or your |
Marko Mikulicic |
0:c0ecb8bf28eb | 4905 | * C buffer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4906 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4907 | * - If you need to convert any JS value to number using common JavaScript |
Marko Mikulicic |
0:c0ecb8bf28eb | 4908 | * semantics, use `to_number_v()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4909 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4910 | * - If you need to convert any JS value to primitive, without forcing it to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4911 | * string or number, use `to_primitive()` (see comments for this function for |
Marko Mikulicic |
0:c0ecb8bf28eb | 4912 | * details); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4913 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4914 | * - If you have a primitive value, and you want to convert it to either string |
Marko Mikulicic |
0:c0ecb8bf28eb | 4915 | * or number, you can still use functions above: `to_string()` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 4916 | * `to_number_v()`. But if you want to save a bit of work, use: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4917 | * - `primitive_to_str()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4918 | * - `primitive_to_number()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4919 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4920 | * In fact, these are a bit lower level functions, which are used by |
Marko Mikulicic |
0:c0ecb8bf28eb | 4921 | * `to_string()` and `to_number_v()` after converting value to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4922 | * primitive. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4923 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4924 | * - If you want to call `valueOf()` on the object, use `obj_value_of()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4925 | * - If you want to call `toString()` on the object, use `obj_to_string()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4926 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4927 | * - If you need to convert any JS value to boolean using common JavaScript |
Marko Mikulicic |
0:c0ecb8bf28eb | 4928 | * semantics (as in the expression `if (v)` or `Boolean(v)`), use |
Marko Mikulicic |
0:c0ecb8bf28eb | 4929 | * `to_boolean_v()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4930 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4931 | * - If you want to get the JSON representation of a value, use |
Marko Mikulicic |
0:c0ecb8bf28eb | 4932 | * `to_json_or_debug()`, passing `0` as `is_debug` : writes data to your C |
Marko Mikulicic |
0:c0ecb8bf28eb | 4933 | * buffer; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4934 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4935 | * - There is one more kind of representation: `DEBUG`. It's very similar to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4936 | * JSON, but it will not omit non-JSON values, such as functions. Again, use |
Marko Mikulicic |
0:c0ecb8bf28eb | 4937 | * `to_json_or_debug()`, but pass `1` as `is_debug` this time: writes data to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4938 | * your C buffer; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4939 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4940 | * Additionally, for any kind of to-string conversion into C buffer, you can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4941 | * use a convenience wrapper function (mostly for public API), which can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4942 | * allocate the buffer for you: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4943 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4944 | * - `v7_stringify_throwing()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4945 | * - `v7_stringify()` : the same as above, but doesn't throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4946 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4947 | * There are a couple of more specific conversions, which I'd like to probably |
Marko Mikulicic |
0:c0ecb8bf28eb | 4948 | * refactor or remove in the future: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4949 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4950 | * - `to_long()` : if given value is `undefined`, returns provided default |
Marko Mikulicic |
0:c0ecb8bf28eb | 4951 | * value; otherwise, converts value to number, and then truncates to `long`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4952 | * - `str_to_ulong()` : converts the value to string, and tries to parse it as |
Marko Mikulicic |
0:c0ecb8bf28eb | 4953 | * an integer. Use it if only you need strong conformity ov the value to an |
Marko Mikulicic |
0:c0ecb8bf28eb | 4954 | * integer (currently, it's used only when examining keys of array object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4955 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4956 | * ---------------------------------------------------------------------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 4957 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4958 | * TODO(dfrank): |
Marko Mikulicic |
0:c0ecb8bf28eb | 4959 | * - Rename functions like `v7_get_double(v7, )`, `get_object_struct()` to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4960 | *something |
Marko Mikulicic |
0:c0ecb8bf28eb | 4961 | * that will clearly identify that they convert to some C entity, not |
Marko Mikulicic |
0:c0ecb8bf28eb | 4962 | * `v7_val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4963 | * - Maybe make `to_string()` private? But then, there will be no way |
Marko Mikulicic |
0:c0ecb8bf28eb | 4964 | * in public API to convert value to `v7_val_t` string, so, for now |
Marko Mikulicic |
0:c0ecb8bf28eb | 4965 | * it's here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4966 | * - When we agree on what goes to public API, and what does not, write |
Marko Mikulicic |
0:c0ecb8bf28eb | 4967 | * similar conversion guide for public API (in `conversion_public.h`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4968 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4970 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4971 | * Convert any JS value to number, using common JavaScript semantics: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4972 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4973 | * - If value is an object: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4974 | * - call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4975 | * - If `valueOf()` returned non-primitive value, call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4976 | * - If `toString()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4977 | * - Now we have a primitive, and if it's not a number, then: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4978 | * - If `undefined`, return `NaN` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4979 | * - If `null`, return 0.0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 4980 | * - If boolean, return either 1 or 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 4981 | * - If string, try to parse it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4982 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4983 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4984 | V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, v7_val_t v, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4985 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4986 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4987 | * Convert any JS value to string, using common JavaScript semantics, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4988 | * see `v7_stringify()` and `V7_STRINGIFY_DEFAULT`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4989 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4990 | * This function can return multiple things: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4991 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4992 | * - String as a `v7_val_t` (if `res` is not `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4993 | * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 4994 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4995 | * - Length of actual string, independently of `buf_size` (if `res_len` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 4996 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4997 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4998 | * The rationale of having multiple formats of returned value is the following: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4999 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5000 | * Initially, to-string conversion always returned `v7_val_t`. But it turned |
Marko Mikulicic |
0:c0ecb8bf28eb | 5001 | * out that there are situations where such an approach adds useless pressure |
Marko Mikulicic |
0:c0ecb8bf28eb | 5002 | * on GC: e.g. when converting `undefined` to string, and the caller actually |
Marko Mikulicic |
0:c0ecb8bf28eb | 5003 | * needs a C buffer, not a `v7_val_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5004 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5005 | * Always returning string through `buf`+`buf_size` is bad as well: if we |
Marko Mikulicic |
0:c0ecb8bf28eb | 5006 | * convert from object to string, and either `toString()` or `valueOf()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5007 | * returned string, then we'd have to get string data from it, write to buffer, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5008 | * and if caller actually need `v7_val_t`, then it will have to create new |
Marko Mikulicic |
0:c0ecb8bf28eb | 5009 | * instance of the same string: again, useless GC pressure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5010 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5011 | * So, we have to use the combined approach. This function will make minimal |
Marko Mikulicic |
0:c0ecb8bf28eb | 5012 | * work depending on give `res` and `buf`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5013 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5014 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5015 | V7_PRIVATE enum v7_err to_string(struct v7 *v7, v7_val_t v, v7_val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5016 | char *buf, size_t buf_size, size_t *res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5018 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5019 | * Convert value to primitive, if it's not already. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5020 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5021 | * For object-to-primitive conversion, each object in JavaScript has two |
Marko Mikulicic |
0:c0ecb8bf28eb | 5022 | * methods: `toString()` and `valueOf()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5023 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5024 | * When converting object to string, JavaScript does the following: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5025 | * - call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5026 | * - If `toString()` returned non-primitive value, call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5027 | * - If `valueOf()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5028 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5029 | * When converting object to number, JavaScript calls the same functions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5030 | * but in reverse: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5031 | * - call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5032 | * - If `valueOf()` returned non-primitive value, call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5033 | * - If `toString()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5034 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5035 | * This function `to_primitive()` performs either type of conversion, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5036 | * depending on the `hint` argument (see `enum to_primitive_hint`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5037 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5038 | enum to_primitive_hint { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5039 | /* Call `valueOf()` first, then `toString()` if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5040 | V7_TO_PRIMITIVE_HINT_NUMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5042 | /* Call `toString()` first, then `valueOf()` if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5043 | V7_TO_PRIMITIVE_HINT_STRING, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5045 | /* STRING for Date, NUMBER for everything else */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5046 | V7_TO_PRIMITIVE_HINT_AUTO, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5047 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5048 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5049 | enum v7_err to_primitive(struct v7 *v7, v7_val_t v, enum to_primitive_hint hint, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5050 | v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5052 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5053 | * Convert primitive value to string, using common JavaScript semantics. If |
Marko Mikulicic |
0:c0ecb8bf28eb | 5054 | * you need to convert any value to string (either object or primitive), |
Marko Mikulicic |
0:c0ecb8bf28eb | 5055 | * see `to_string()` or `v7_stringify_throwing()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5056 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5057 | * This function can return multiple things: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5058 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5059 | * - String as a `v7_val_t` (if `res` is not `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5060 | * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 5061 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5062 | * - Length of actual string, independently of `buf_size` (if `res_len` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 5063 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5064 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5065 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5066 | V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5067 | char *buf, size_t buf_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5068 | size_t *res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5070 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5071 | * Convert primitive value to number, using common JavaScript semantics. If you |
Marko Mikulicic |
0:c0ecb8bf28eb | 5072 | * need to convert any value to number (either object or primitive), see |
Marko Mikulicic |
0:c0ecb8bf28eb | 5073 | * `to_number_v()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5074 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5075 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5076 | V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5078 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5079 | * Convert value to JSON or "debug" representation, depending on whether |
Marko Mikulicic |
0:c0ecb8bf28eb | 5080 | * `is_debug` is non-zero. The "debug" is the same as JSON, but non-JSON values |
Marko Mikulicic |
0:c0ecb8bf28eb | 5081 | * (functions, `undefined`, etc) will not be omitted. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5082 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5083 | * See also `v7_stringify()`, `v7_stringify_throwing()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5084 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5085 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5086 | V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5087 | size_t size, size_t *res_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5088 | uint8_t is_debug); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5089 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5090 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5091 | * Calls `valueOf()` on given object `v` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5092 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5093 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5094 | V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5095 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5096 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5097 | * Calls `toString()` on given object `v` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5098 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5099 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5100 | V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5102 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5103 | * If given value is `undefined`, returns `default_value`; otherwise, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5104 | * converts value to number, and then truncates to `long`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5105 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5106 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5107 | V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5108 | long *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5110 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5111 | * Converts value to boolean as in the expression `if (v)` or `Boolean(v)`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5112 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5113 | * NOTE: it can't throw (even if the given value is an object with `valueOf()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5114 | * that throws), so it returns `val_t` directly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5115 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5116 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5117 | V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5118 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5119 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5120 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5121 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5123 | #endif /* CS_V7_SRC_CONVERSION_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5124 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5125 | #line 1 "v7/src/varint.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5126 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5127 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5128 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5129 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5130 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5132 | #ifndef CS_V7_SRC_VARINT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5133 | #define CS_V7_SRC_VARINT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5135 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5136 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5137 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5138 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5139 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5141 | V7_PRIVATE int encode_varint(size_t len, unsigned char *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5142 | V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5143 | V7_PRIVATE int calc_llen(size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5145 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5146 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5147 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5148 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5149 | #endif /* CS_V7_SRC_VARINT_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5150 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5151 | #line 1 "common/cs_strtod.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5152 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5153 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5154 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5155 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5156 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5158 | #ifndef CS_COMMON_CS_STRTOD_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5159 | #define CS_COMMON_CS_STRTOD_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5161 | double cs_strtod(const char *str, char **endptr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5162 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5163 | #endif /* CS_COMMON_CS_STRTOD_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5164 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5165 | #line 1 "v7/src/ast.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5166 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5167 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5168 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5169 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5170 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5172 | #ifndef CS_V7_SRC_AST_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5173 | #define CS_V7_SRC_AST_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5175 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 5176 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5177 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5178 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5180 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5182 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5183 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5184 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5186 | #define BIN_AST_SIGNATURE "V\007ASTV10" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5187 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5188 | enum ast_tag { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5189 | AST_NOP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5190 | AST_SCRIPT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5191 | AST_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5192 | AST_VAR_DECL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5193 | AST_FUNC_DECL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5194 | AST_IF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5195 | AST_FUNC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5197 | AST_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5198 | AST_REM_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5199 | AST_MUL_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5200 | AST_DIV_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5201 | AST_XOR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5202 | AST_PLUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5203 | AST_MINUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5204 | AST_OR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5205 | AST_AND_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5206 | AST_LSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5207 | AST_RSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5208 | AST_URSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5210 | AST_NUM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5211 | AST_IDENT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5212 | AST_STRING, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5213 | AST_REGEX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5214 | AST_LABEL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5216 | AST_SEQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5217 | AST_WHILE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5218 | AST_DOWHILE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5219 | AST_FOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5220 | AST_FOR_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5221 | AST_COND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5223 | AST_DEBUGGER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5224 | AST_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5225 | AST_LABELED_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5226 | AST_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5227 | AST_LABELED_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5228 | AST_RETURN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5229 | AST_VALUE_RETURN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5230 | AST_THROW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5232 | AST_TRY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5233 | AST_SWITCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5234 | AST_CASE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5235 | AST_DEFAULT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5236 | AST_WITH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5238 | AST_LOGICAL_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5239 | AST_LOGICAL_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5240 | AST_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5241 | AST_XOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5242 | AST_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5244 | AST_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5245 | AST_EQ_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5246 | AST_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5247 | AST_NE_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5249 | AST_LE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5250 | AST_LT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5251 | AST_GE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5252 | AST_GT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5253 | AST_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5254 | AST_INSTANCEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5256 | AST_LSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5257 | AST_RSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5258 | AST_URSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5259 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5260 | AST_ADD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5261 | AST_SUB, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5263 | AST_REM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5264 | AST_MUL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5265 | AST_DIV, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5267 | AST_POSITIVE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5268 | AST_NEGATIVE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5269 | AST_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5270 | AST_LOGICAL_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5271 | AST_VOID, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5272 | AST_DELETE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5273 | AST_TYPEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5274 | AST_PREINC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5275 | AST_PREDEC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5277 | AST_POSTINC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5278 | AST_POSTDEC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5280 | AST_MEMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5281 | AST_INDEX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5282 | AST_CALL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5284 | AST_NEW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5286 | AST_ARRAY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5287 | AST_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5288 | AST_PROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5289 | AST_GETTER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5290 | AST_SETTER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5292 | AST_THIS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5293 | AST_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5294 | AST_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5295 | AST_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5296 | AST_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5298 | AST_USE_STRICT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5299 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5300 | AST_MAX_TAG |
Marko Mikulicic |
0:c0ecb8bf28eb | 5301 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5303 | struct ast { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5304 | struct mbuf mbuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5305 | int refcnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5306 | int has_overflow; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5307 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5309 | typedef unsigned long ast_off_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5311 | #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5312 | #define GCC_HAS_PRAGMA_DIAGNOSTIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 5313 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5315 | #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 5316 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5317 | * TODO(mkm): GCC complains that bitfields on char are not standard |
Marko Mikulicic |
0:c0ecb8bf28eb | 5318 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5319 | #pragma GCC diagnostic push |
Marko Mikulicic |
0:c0ecb8bf28eb | 5320 | #pragma GCC diagnostic ignored "-Wpedantic" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5321 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5322 | struct ast_node_def { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5323 | #ifndef V7_DISABLE_AST_TAG_NAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5324 | const char *name; /* tag name, for debugging and serialization */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5325 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5326 | unsigned char has_varint : 1; /* has a varint body */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5327 | unsigned char has_inlined : 1; /* inlined data whose size is in varint fld */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5328 | unsigned char num_skips : 3; /* number of skips */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5329 | unsigned char num_subtrees : 3; /* number of fixed subtrees */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5330 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5331 | extern const struct ast_node_def ast_node_defs[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5332 | #if V7_ENABLE_FOOTPRINT_REPORT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5333 | extern const size_t ast_node_defs_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5334 | extern const size_t ast_node_defs_count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5335 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5336 | #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 5337 | #pragma GCC diagnostic pop |
Marko Mikulicic |
0:c0ecb8bf28eb | 5338 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5340 | enum ast_which_skip { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5341 | AST_END_SKIP = 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5342 | AST_VAR_NEXT_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5343 | AST_SCRIPT_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5344 | AST_FOR_BODY_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5345 | AST_DO_WHILE_COND_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5346 | AST_END_IF_TRUE_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5347 | AST_TRY_CATCH_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5348 | AST_TRY_FINALLY_SKIP = 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5349 | AST_FUNC_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5350 | AST_FUNC_BODY_SKIP = 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5351 | AST_SWITCH_DEFAULT_SKIP = 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5352 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5354 | V7_PRIVATE void ast_init(struct ast *, size_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5355 | V7_PRIVATE void ast_optimize(struct ast *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5356 | V7_PRIVATE void ast_free(struct ast *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5358 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5359 | * Begins an AST node by inserting a tag to the AST at the given offset. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5360 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5361 | * It also allocates space for the fixed_size payload and the space for |
Marko Mikulicic |
0:c0ecb8bf28eb | 5362 | * the skips. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5363 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5364 | * The caller is responsible for appending children. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5365 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5366 | * Returns the offset of the node payload (one byte after the tag). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5367 | * This offset can be passed to `ast_set_skip`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5368 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5369 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5370 | ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5371 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5372 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5373 | * Modify tag which is already added to buffer. Keeps `AST_TAG_LINENO_PRESENT` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5374 | * flag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5375 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5376 | V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5377 | enum ast_tag tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5379 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 5380 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5381 | * Add line_no varint after all skips of the tag at the offset `tag_off`, and |
Marko Mikulicic |
0:c0ecb8bf28eb | 5382 | * marks the tag byte. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5383 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5384 | * Byte at the offset `tag_off` should be a valid tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5385 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5386 | V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5387 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5389 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5390 | * Patches a given skip slot for an already emitted node with the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5391 | * current write cursor position (e.g. AST length). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5392 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5393 | * This is intended to be invoked when a node with a variable number |
Marko Mikulicic |
0:c0ecb8bf28eb | 5394 | * of child subtrees is closed, or when the consumers need a shortcut |
Marko Mikulicic |
0:c0ecb8bf28eb | 5395 | * to the next sibling. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5396 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5397 | * Each node type has a different number and semantic for skips, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5398 | * all of them defined in the `ast_which_skip` enum. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5399 | * All nodes having a variable number of child subtrees must define |
Marko Mikulicic |
0:c0ecb8bf28eb | 5400 | * at least the `AST_END_SKIP` skip, which effectively skips a node |
Marko Mikulicic |
0:c0ecb8bf28eb | 5401 | * boundary. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5402 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5403 | * Every tree reader can assume this and safely skip unknown nodes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5404 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5405 | * `pos` should be an offset of the byte right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5406 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5407 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5408 | ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5410 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5411 | * Patches a given skip slot for an already emitted node with the value |
Marko Mikulicic |
0:c0ecb8bf28eb | 5412 | * (stored as delta relative to the `pos` node) of the `where` argument. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5413 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5414 | V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5415 | ast_off_t where, enum ast_which_skip skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5417 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5418 | * Returns the offset in AST to which the given `skip` points. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5419 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5420 | * `pos` should be an offset of the byte right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5421 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5422 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5423 | ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5425 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5426 | * Returns the tag from the offset `ppos`, and shifts `ppos` by 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5427 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5428 | V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5430 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5431 | * Moves the cursor to the tag's varint and inlined data (if there are any, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 5432 | * `struct ast_node_def::has_varint` and `struct ast_node_def::has_inlined`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5433 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5434 | * Technically, it skips node's "skips" and line number data, if either is |
Marko Mikulicic |
0:c0ecb8bf28eb | 5435 | * present. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5436 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5437 | * Assumes a cursor (`ppos`) positioned right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5438 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5439 | V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5441 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5442 | * Moves the cursor to the tag's subtrees (if there are any, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5443 | * see `struct ast_node_def::num_subtrees`), or to the next node in case the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5444 | * current node has no subtrees. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5445 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5446 | * Technically, it skips node's "skips", line number data, and inlined data, if |
Marko Mikulicic |
0:c0ecb8bf28eb | 5447 | * either is present. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5448 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5449 | * Assumes a cursor (`ppos`) positioned right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5450 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5451 | V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5453 | /* Helper to add a node with inlined data. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5454 | V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5455 | enum ast_tag tag, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5456 | size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5457 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5458 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5459 | * Returns the line number encoded in the node, or `0` in case of none is |
Marko Mikulicic |
0:c0ecb8bf28eb | 5460 | * encoded. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5461 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5462 | * `pos` should be an offset of the byte right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5463 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5464 | V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5466 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5467 | * `pos` should be an offset of the byte right after a tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 5468 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5469 | V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5471 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5472 | * Returns the `double` number inlined in the node |
Marko Mikulicic |
0:c0ecb8bf28eb | 5473 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5474 | V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5475 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5476 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5477 | * Skips the node and all its subnodes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5478 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5479 | * Cursor (`ppos`) should be at the tag byte |
Marko Mikulicic |
0:c0ecb8bf28eb | 5480 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5481 | V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5483 | V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5484 | int depth); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5486 | V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5488 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5489 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5490 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5492 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5494 | #endif /* CS_V7_SRC_AST_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5495 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5496 | #line 1 "v7/src/bcode.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5497 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5498 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5499 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5500 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5501 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5502 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5503 | #ifndef CS_V7_SRC_BCODE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5504 | #define CS_V7_SRC_BCODE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5506 | #define BIN_BCODE_SIGNATURE "V\007BCODE:" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5508 | #if !defined(V7_NAMES_CNT_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5509 | #define V7_NAMES_CNT_WIDTH 10 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5510 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5512 | #if !defined(V7_ARGS_CNT_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5513 | #define V7_ARGS_CNT_WIDTH 8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5514 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5515 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5516 | #define V7_NAMES_CNT_MAX ((1 << V7_NAMES_CNT_WIDTH) - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5517 | #define V7_ARGS_CNT_MAX ((1 << V7_ARGS_CNT_WIDTH) - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5519 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5520 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5521 | /* Amalgamated: #include "v7/src/opcodes.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5522 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5523 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5524 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5525 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5527 | enum bcode_inline_lit_type_tag { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5528 | BCODE_INLINE_STRING_TYPE_TAG = 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5529 | BCODE_INLINE_NUMBER_TYPE_TAG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5530 | BCODE_INLINE_FUNC_TYPE_TAG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5531 | BCODE_INLINE_REGEXP_TYPE_TAG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5533 | BCODE_MAX_INLINE_TYPE_TAG |
Marko Mikulicic |
0:c0ecb8bf28eb | 5534 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5536 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5537 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5538 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5540 | typedef uint32_t bcode_off_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5542 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5543 | * Each JS function will have one bcode structure |
Marko Mikulicic |
0:c0ecb8bf28eb | 5544 | * containing the instruction stream, a literal table, and function |
Marko Mikulicic |
0:c0ecb8bf28eb | 5545 | * metadata. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5546 | * Instructions contain references to literals (strings, constants, etc) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5547 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5548 | * The bcode struct can be shared between function instances |
Marko Mikulicic |
0:c0ecb8bf28eb | 5549 | * and keeps a reference count used to free it in the function destructor. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5550 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5551 | struct bcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5552 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5553 | * Names + instruction opcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5554 | * Names are null-terminates strings. For function's bcode, there are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5555 | * - function name (for anonymous function, the name is still present: an |
Marko Mikulicic |
0:c0ecb8bf28eb | 5556 | * empty string); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5557 | * - arg names (a number of args is determined by `args_cnt`, see below); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5558 | * - local names (a number or locals can be calculated: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5559 | * `(names_cnt - args_cnt - 1)`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5560 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5561 | * For script's bcode, there are just local names. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5562 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5563 | struct v7_vec ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5565 | /* Literal table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5566 | struct v7_vec lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5567 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5568 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5569 | /* Name of the file from which this bcode was generated (used for debug) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5570 | void *filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5571 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5573 | /* Reference count */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5574 | uint8_t refcnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5576 | /* Total number of null-terminated strings in the beginning of `ops` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5577 | unsigned int names_cnt : V7_NAMES_CNT_WIDTH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5578 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5579 | /* Number of args (should be <= `(names_cnt + 1)`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5580 | unsigned int args_cnt : V7_ARGS_CNT_WIDTH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5582 | unsigned int strict_mode : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5583 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5584 | * If true this structure lives on read only memory, either |
Marko Mikulicic |
0:c0ecb8bf28eb | 5585 | * mmapped or constant data section. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5586 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5587 | unsigned int frozen : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5589 | /* If set, `ops.buf` points to ROM, so we shouldn't free it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5590 | unsigned int ops_in_rom : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5591 | /* Set for deserialized bcode. Used for metrics only */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5592 | unsigned int deserialized : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5594 | /* Set when `ops` contains function name as the first `name` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5595 | unsigned int func_name_present : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5597 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5598 | /* If set, `filename` points to ROM, so we shouldn't free it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5599 | unsigned int filename_in_rom : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5600 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5601 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5603 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5604 | * Bcode builder context: it contains mutable mbufs for opcodes and literals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5605 | * whereas the bcode itself contains just vectors (`struct v7_vec`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5606 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5607 | struct bcode_builder { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5608 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5609 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5611 | struct mbuf ops; /* names + instruction opcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5612 | struct mbuf lit; /* literal table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5613 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5615 | V7_PRIVATE void bcode_builder_init(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5616 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5617 | struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5618 | V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5620 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5621 | * Note: `filename` must be either: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5622 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5623 | * - `NULL`. In this case, `filename_in_rom` is ignored. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5624 | * - A pointer to ROM (or to any other unmanaged memory). `filename_in_rom` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5625 | * must be set to 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5626 | * - A pointer returned by `shdata_create()`, i.e. a pointer to shared data. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5627 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5628 | * If you need to copy filename from another bcode, just pass NULL initially, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5629 | * and after bcode is initialized, call `bcode_copy_filename_from()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5630 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5631 | * To get later a proper null-terminated filename string from bcode, use |
Marko Mikulicic |
0:c0ecb8bf28eb | 5632 | * `bcode_get_filename()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5633 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5634 | V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5635 | void *filename, uint8_t filename_in_rom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5636 | V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5637 | V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5638 | V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5640 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5641 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5642 | * Return a pointer to null-terminated filename string |
Marko Mikulicic |
0:c0ecb8bf28eb | 5643 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5644 | V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5645 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5646 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5647 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5648 | * Copy filename from `src` to `dst`. If source filename is a pointer to ROM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5649 | * then just the pointer is copied; otherwise, appropriate shdata pointer is |
Marko Mikulicic |
0:c0ecb8bf28eb | 5650 | * retained. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5651 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5652 | V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5654 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5655 | * Serialize a bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5656 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5657 | * All literals, including functions, are inlined into `ops` data; see |
Marko Mikulicic |
0:c0ecb8bf28eb | 5658 | * the serialization logic in `bcode_op_lit()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5659 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5660 | * The root bcode looks just like a regular function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5661 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5662 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5663 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5664 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5665 | /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5666 | FILE *f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5668 | V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5669 | const char *data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5671 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 5672 | V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *, struct bcode *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5673 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5675 | /* mode of literal storage: in literal table or inlined in `ops` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5676 | enum lit_mode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5677 | /* literal stored in table, index is in `lit_t::lit_idx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5678 | LIT_MODE__TABLE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5679 | /* literal should be inlined in `ops`, value is in `lit_t::inline_val` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5680 | LIT_MODE__INLINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5681 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5683 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5684 | * Result of the addition of literal value to bcode (see `bcode_add_lit()`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5685 | * There are two possible cases: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5686 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5687 | * - Literal is added to the literal table. In this case, `mode == |
Marko Mikulicic |
0:c0ecb8bf28eb | 5688 | * LIT_MODE__TABLE`, and the index of the literal is stored in `lit_idx` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5689 | * - Literal is not added anywhere, and should be inlined into `ops`. In this |
Marko Mikulicic |
0:c0ecb8bf28eb | 5690 | * case, `mode == LIT_MODE__INLINED`, and the value to inline is stored in |
Marko Mikulicic |
0:c0ecb8bf28eb | 5691 | * `inline_val`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5692 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5693 | * It's `bcode_op_lit()` who handles both of these cases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5694 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5695 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5696 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5697 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5698 | * index in literal table; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5699 | * NOTE: valid if only `mode == LIT_MODE__TABLE` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5700 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5701 | size_t lit_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5702 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5703 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5704 | * value to be inlined into `ops`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5705 | * NOTE: valid if only `mode == LIT_MODE__INLINED` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5706 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5707 | v7_val_t inline_val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5708 | } v; /* anonymous unions are a c11 feature */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5710 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5711 | * mode of literal storage (see `enum lit_mode`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5712 | * NOTE: we need one more bit, because enum can be signed |
Marko Mikulicic |
0:c0ecb8bf28eb | 5713 | * on some compilers (e.g. msvc) and thus will get signextended |
Marko Mikulicic |
0:c0ecb8bf28eb | 5714 | * when moved to a `enum lit_mode` variable basically corrupting |
Marko Mikulicic |
0:c0ecb8bf28eb | 5715 | * the value. See https://github.com/cesanta/v7/issues/551 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5716 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5717 | enum lit_mode mode : 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5718 | } lit_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5719 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5720 | V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5722 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 5723 | V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5724 | int line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5725 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5727 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5728 | * Add a literal to the bcode literal table, or just decide that the literal |
Marko Mikulicic |
0:c0ecb8bf28eb | 5729 | * should be inlined into `ops`. See `lit_t` for details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5730 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5731 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5732 | lit_t bcode_add_lit(struct bcode_builder *bbuilder, v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5733 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5734 | /* disabled because of short lits */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5735 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5736 | V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5737 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5739 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5740 | * Emit an opcode `op`, and handle the literal `lit` (see `bcode_add_lit()`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5741 | * `lit_t`). Depending on the literal storage mode (see `enum lit_mode`), this |
Marko Mikulicic |
0:c0ecb8bf28eb | 5742 | * function either emits literal table index or inlines the literal directly |
Marko Mikulicic |
0:c0ecb8bf28eb | 5743 | * into `ops.` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5744 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5745 | V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5746 | lit_t lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5748 | /* Helper function, equivalent of `bcode_op_lit(bbuilder, OP_PUSH_LIT, lit)` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5749 | V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5751 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5752 | * Add name to bcode. If `idx` is null, a name is appended to the end of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5753 | * `bcode->ops.buf`. If `idx` is provided, it should point to the index at |
Marko Mikulicic |
0:c0ecb8bf28eb | 5754 | * which new name should be inserted; and it is updated by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5755 | * `bcode_add_name()` to point right after newly added name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5756 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5757 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5758 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5759 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5760 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5761 | /*V7_PRIVATE*/ enum v7_err |
Marko Mikulicic |
0:c0ecb8bf28eb | 5762 | bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5763 | size_t *idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5764 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5765 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5766 | * Takes a pointer to the beginning of `ops` buffer and names count, returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 5767 | * a pointer where actual opcodes begin (i.e. skips names). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5768 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5769 | * It takes two distinct arguments instead of just `struct bcode` pointer, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5770 | * because during bcode building `ops` is stored in builder. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5771 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5772 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5773 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5774 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5775 | /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5777 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5778 | * Given a pointer to `ops` (which should be `bcode->ops` or a pointer returned |
Marko Mikulicic |
0:c0ecb8bf28eb | 5779 | * from previous invocation of `bcode_next_name()`), yields a name string via |
Marko Mikulicic |
0:c0ecb8bf28eb | 5780 | * arguments `pname`, `plen`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5781 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5782 | * Returns a pointer that should be given to `bcode_next_name()` to get a next |
Marko Mikulicic |
0:c0ecb8bf28eb | 5783 | * string (Whether there is a next string should be determined via the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5784 | * `names_cnt`; since if there are no more names, this function will return an |
Marko Mikulicic |
0:c0ecb8bf28eb | 5785 | * invalid non-null pointer as next name pointer) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5786 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5787 | V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5789 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5790 | * Like `bcode_next_name()`, but instead of yielding a C string, it yields a |
Marko Mikulicic |
0:c0ecb8bf28eb | 5791 | * `val_t` value (via `res`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5792 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5793 | V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5794 | char *ops, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5796 | V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5798 | V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5799 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5800 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5801 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5802 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5803 | /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5804 | uint8_t op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5805 | /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5806 | bcode_off_t label, bcode_off_t target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5808 | V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5809 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5810 | * Reads varint-encoded integer from the provided pointer, and adjusts |
Marko Mikulicic |
0:c0ecb8bf28eb | 5811 | * the pointer appropriately |
Marko Mikulicic |
0:c0ecb8bf28eb | 5812 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5813 | V7_PRIVATE size_t bcode_get_varint(char **ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5815 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5816 | * Decode a literal value from a string of opcodes and update the cursor to |
Marko Mikulicic |
0:c0ecb8bf28eb | 5817 | * point past it |
Marko Mikulicic |
0:c0ecb8bf28eb | 5818 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5819 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5820 | v7_val_t bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5821 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5822 | #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5823 | V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5824 | char **ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5825 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5827 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5828 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5829 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5831 | #endif /* CS_V7_SRC_BCODE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5832 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5833 | #line 1 "v7/src/gc_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5834 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5835 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5836 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5837 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5838 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5840 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5841 | * === Garbage Collector |
Marko Mikulicic |
0:c0ecb8bf28eb | 5842 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5843 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5844 | #ifndef CS_V7_SRC_GC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5845 | #define CS_V7_SRC_GC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5846 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5847 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5849 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5850 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5851 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5853 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 5854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5855 | /* Heap metric id, see `v7_heap_stat()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5856 | enum v7_heap_stat_what { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5857 | V7_HEAP_STAT_HEAP_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5858 | V7_HEAP_STAT_HEAP_USED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5859 | V7_HEAP_STAT_STRING_HEAP_RESERVED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5860 | V7_HEAP_STAT_STRING_HEAP_USED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5861 | V7_HEAP_STAT_OBJ_HEAP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5862 | V7_HEAP_STAT_OBJ_HEAP_FREE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5863 | V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5864 | V7_HEAP_STAT_FUNC_HEAP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5865 | V7_HEAP_STAT_FUNC_HEAP_FREE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5866 | V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5867 | V7_HEAP_STAT_PROP_HEAP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5868 | V7_HEAP_STAT_PROP_HEAP_FREE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5869 | V7_HEAP_STAT_PROP_HEAP_CELL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5870 | V7_HEAP_STAT_FUNC_AST_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5871 | V7_HEAP_STAT_BCODE_OPS_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5872 | V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5873 | V7_HEAP_STAT_BCODE_LIT_DESER_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5874 | V7_HEAP_STAT_FUNC_OWNED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5875 | V7_HEAP_STAT_FUNC_OWNED_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 5876 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5878 | /* Returns a given heap statistics */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5879 | int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5880 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5882 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5883 | * Perform garbage collection. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5884 | * Pass true to full in order to reclaim unused heap back to the OS. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5885 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5886 | void v7_gc(struct v7 *v7, int full); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5888 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5889 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5890 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5892 | #endif /* CS_V7_SRC_GC_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5893 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5894 | #line 1 "v7/src/gc.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5895 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5896 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5897 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5898 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5899 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5901 | #ifndef CS_V7_SRC_GC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5902 | #define CS_V7_SRC_GC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5904 | /* Amalgamated: #include "v7/src/gc_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5906 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5907 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5909 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5910 | * Macros for marking reachable things: use bit 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5911 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5912 | #define MARK(p) (((struct gc_cell *) (p))->head.word |= 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5913 | #define UNMARK(p) (((struct gc_cell *) (p))->head.word &= ~1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5914 | #define MARKED(p) (((struct gc_cell *) (p))->head.word & 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5916 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5917 | * Similar to `MARK()` / `UNMARK()` / `MARKED()`, but `.._FREE` counterparts |
Marko Mikulicic |
0:c0ecb8bf28eb | 5918 | * are intended to mark free cells (as opposed to used ones), so they use |
Marko Mikulicic |
0:c0ecb8bf28eb | 5919 | * bit 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5920 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5921 | #define MARK_FREE(p) (((struct gc_cell *) (p))->head.word |= 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5922 | #define UNMARK_FREE(p) (((struct gc_cell *) (p))->head.word &= ~2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5923 | #define MARKED_FREE(p) (((struct gc_cell *) (p))->head.word & 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5925 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5926 | * performs arithmetics on gc_cell pointers as if they were arena->cell_size |
Marko Mikulicic |
0:c0ecb8bf28eb | 5927 | * bytes wide |
Marko Mikulicic |
0:c0ecb8bf28eb | 5928 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5929 | #define GC_CELL_OP(arena, cell, op, arg) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5930 | ((struct gc_cell *) (((char *) (cell)) op((arg) * (arena)->cell_size))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5931 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5932 | struct gc_tmp_frame { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5933 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5934 | size_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5935 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5937 | struct gc_cell { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5938 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5939 | struct gc_cell *link; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5940 | uintptr_t word; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5941 | } head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5942 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5944 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5945 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5946 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5948 | V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5949 | V7_PRIVATE struct v7_property *new_property(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5950 | V7_PRIVATE struct v7_js_function *new_function(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5952 | V7_PRIVATE void gc_mark(struct v7 *, val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5954 | V7_PRIVATE void gc_arena_init(struct gc_arena *, size_t, size_t, size_t, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5955 | const char *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5956 | V7_PRIVATE void gc_arena_destroy(struct v7 *, struct gc_arena *a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5957 | V7_PRIVATE void gc_sweep(struct v7 *, struct gc_arena *, size_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5958 | V7_PRIVATE void *gc_alloc_cell(struct v7 *, struct gc_arena *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5960 | V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5961 | V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5962 | V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *, val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5964 | V7_PRIVATE void compute_need_gc(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5965 | /* perform gc if not inhibited */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5966 | V7_PRIVATE int maybe_gc(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5968 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5969 | V7_PRIVATE uint16_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5970 | gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5971 | V7_PRIVATE int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5972 | V7_PRIVATE void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5973 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5975 | V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5976 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5977 | /* return 0 if v is an object/function with a bad pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5978 | V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5980 | /* checks whether a pointer is within the ranges of an arena */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5981 | V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5983 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 5984 | V7_PRIVATE size_t gc_arena_size(struct gc_arena *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5985 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5987 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5988 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5989 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5991 | #endif /* CS_V7_SRC_GC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5992 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5993 | #line 1 "v7/src/regexp_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5994 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5995 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5996 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5997 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5998 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6000 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6001 | * === RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 6002 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6003 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6004 | #ifndef CS_V7_SRC_REGEXP_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6005 | #define CS_V7_SRC_REGEXP_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6007 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6009 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6010 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6011 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6013 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6014 | * Make RegExp object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6015 | * `regex`, `regex_len` specify a pattern, `flags` and `flags_len` specify |
Marko Mikulicic |
0:c0ecb8bf28eb | 6016 | * flags. Both utf8 encoded. For example, `regex` is `(.+)`, `flags` is `gi`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6017 | * If `regex_len` is ~0, `regex` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6018 | * `strlen(regex)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6019 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6020 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6021 | enum v7_err v7_mk_regexp(struct v7 *v7, const char *regex, size_t regex_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6022 | const char *flags, size_t flags_len, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6024 | /* Returns true if given value is a JavaScript RegExp object*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6025 | int v7_is_regexp(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6027 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6028 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6029 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6031 | #endif /* CS_V7_SRC_REGEXP_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6032 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6033 | #line 1 "v7/src/regexp.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6034 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6035 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6036 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6037 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6038 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6040 | #ifndef CS_V7_SRC_REGEXP_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6041 | #define CS_V7_SRC_REGEXP_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6042 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6043 | /* Amalgamated: #include "v7/src/regexp_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6045 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6046 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6047 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 6048 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6049 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6050 | * Maximum number of flags returned by get_regexp_flags_str(). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6051 | * NOTE: does not include null-terminate byte. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6052 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6053 | #define _V7_REGEXP_MAX_FLAGS_LEN 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6054 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6055 | struct v7_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6057 | V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *, v7_val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6059 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6060 | * Generates a string containing regexp flags, e.g. "gi". |
Marko Mikulicic |
0:c0ecb8bf28eb | 6061 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6062 | * `buf` should point to a buffer of minimum `_V7_REGEXP_MAX_FLAGS_LEN` bytes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6063 | * Returns length of the resulted string (saved into `buf`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6064 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6065 | V7_PRIVATE size_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 6066 | get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6067 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6069 | #endif /* CS_V7_SRC_REGEXP_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6070 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6071 | #line 1 "v7/src/function_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6072 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6073 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6074 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6075 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6076 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6078 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6079 | * === Functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 6080 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6081 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6082 | #ifndef CS_V7_SRC_FUNCTION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6083 | #define CS_V7_SRC_FUNCTION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6085 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6086 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6087 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6088 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6089 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6091 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6092 | * Make a JS function object backed by a cfunction. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6093 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6094 | * `func` is a C callback. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6095 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6096 | * A function object is JS object having the Function prototype that holds a |
Marko Mikulicic |
0:c0ecb8bf28eb | 6097 | * cfunction value in a hidden property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6098 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6099 | * The function object will have a `prototype` property holding an object that |
Marko Mikulicic |
0:c0ecb8bf28eb | 6100 | * will be used as the prototype of objects created when calling the function |
Marko Mikulicic |
0:c0ecb8bf28eb | 6101 | * with the `new` operator. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6102 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6103 | v7_val_t v7_mk_function(struct v7 *, v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6104 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6105 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6106 | * Make f a JS function with specified prototype `proto`, so that the resulting |
Marko Mikulicic |
0:c0ecb8bf28eb | 6107 | * function is better suited for the usage as a constructor. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6108 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6109 | v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6110 | v7_val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6112 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6113 | * Make a JS value that holds C/C++ callback pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6114 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6115 | * CAUTION: This is a low-level function value. It's not a real object and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6116 | * cannot hold user defined properties. You should use `v7_mk_function` unless |
Marko Mikulicic |
0:c0ecb8bf28eb | 6117 | * you know what you're doing. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6118 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6119 | v7_val_t v7_mk_cfunction(v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6121 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6122 | * Returns true if given value is callable (i.e. it's either a JS function or |
Marko Mikulicic |
0:c0ecb8bf28eb | 6123 | * cfunction) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6124 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6125 | int v7_is_callable(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6126 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6127 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6128 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6129 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6131 | #endif /* CS_V7_SRC_FUNCTION_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6132 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6133 | #line 1 "v7/src/function.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6134 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6135 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6136 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6137 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6138 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6140 | #ifndef CS_V7_SRC_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6141 | #define CS_V7_SRC_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6143 | /* Amalgamated: #include "v7/src/function_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6145 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6146 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6147 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6148 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6149 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6150 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6151 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6152 | V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6153 | V7_PRIVATE val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 6154 | mk_js_function(struct v7 *v7, struct v7_generic_object *scope, val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6155 | V7_PRIVATE int is_js_function(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6156 | V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6158 | /* Returns true if given value holds a pointer to C callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6159 | V7_PRIVATE int is_cfunction_lite(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6161 | /* Returns true if given value holds an object which represents C callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6162 | V7_PRIVATE int is_cfunction_obj(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6164 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6165 | * Returns `v7_cfunction_t *` callback pointer stored in `v7_val_t`, or NULL |
Marko Mikulicic |
0:c0ecb8bf28eb | 6166 | * if given value is neither cfunction pointer nor cfunction object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6167 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6168 | V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6170 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6171 | * Like v7_mk_function but also sets the function's `length` property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6172 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6173 | * The `length` property is useful for introspection and the stdlib defines it |
Marko Mikulicic |
0:c0ecb8bf28eb | 6174 | * for many core functions mostly because the ECMA test suite requires it and we |
Marko Mikulicic |
0:c0ecb8bf28eb | 6175 | * don't want to skip otherwise useful tests just because the `length` property |
Marko Mikulicic |
0:c0ecb8bf28eb | 6176 | * check fails early in the test. User defined functions don't need to specify |
Marko Mikulicic |
0:c0ecb8bf28eb | 6177 | * the length and passing -1 is a safe choice, as it will also reduce the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6178 | * footprint. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6179 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6180 | * The subtle difference between set `length` explicitly to 0 rather than |
Marko Mikulicic |
0:c0ecb8bf28eb | 6181 | * just defaulting the `0` value from the prototype is that in the former case |
Marko Mikulicic |
0:c0ecb8bf28eb | 6182 | * the property cannot be change since it's read only. This again, is important |
Marko Mikulicic |
0:c0ecb8bf28eb | 6183 | * only for ecma compliance and your user code might or might not find this |
Marko Mikulicic |
0:c0ecb8bf28eb | 6184 | * relevant. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6185 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6186 | * NODO(lsm): please don't combine v7_mk_function_arg and v7_mk_function |
Marko Mikulicic |
0:c0ecb8bf28eb | 6187 | * into one function. Currently `num_args` is useful only internally. External |
Marko Mikulicic |
0:c0ecb8bf28eb | 6188 | * users can just use `v7_def` to set the length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6189 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6190 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 6191 | v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *func, int num_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6192 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6193 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6194 | * Like v7_mk_function_with_proto but also sets the function's `length` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6195 | *property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6196 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6197 | * NODO(lsm): please don't combine mk_cfunction_obj_with_proto and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6198 | * v7_mk_function_with_proto. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6199 | * into one function. Currently `num_args` is useful only internally. External |
Marko Mikulicic |
0:c0ecb8bf28eb | 6200 | * users can just use `v7_def` to set the length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6201 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6202 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 6203 | v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7, v7_cfunction_t *f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6204 | int num_args, v7_val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6205 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6206 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6207 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6208 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6210 | #endif /* CS_V7_SRC_FUNCTION_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6211 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6212 | #line 1 "v7/src/util_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6213 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6214 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6215 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6216 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6217 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6218 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6219 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6220 | * === Utility functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 6221 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6223 | #ifndef CS_V7_SRC_UTIL_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6224 | #define CS_V7_SRC_UTIL_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6226 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6228 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6229 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6230 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6232 | /* Output a string representation of the value to stdout. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6233 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6234 | void v7_print(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6236 | /* Output a string representation of the value to stdout followed by a newline. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6237 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6238 | void v7_println(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6239 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6240 | /* Output a string representation of the value to a file. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6241 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6242 | void v7_fprint(FILE *f, struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6244 | /* Output a string representation of the value to a file followed by a newline. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6245 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6246 | void v7_fprintln(FILE *f, struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6248 | /* Output stack trace recorded in the exception `e` to file `f` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6249 | void v7_fprint_stack_trace(FILE *f, struct v7 *v7, v7_val_t e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6251 | /* Output error object message and possibly stack trace to f */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6252 | void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, v7_val_t e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6253 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6254 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6256 | struct v7_property; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6257 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6258 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6259 | * C callback, analogue of JS callback `getOwnPropertyDescriptor()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6260 | * Callbacks of this type are used for C API only, see `m7_mk_proxy()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6261 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6262 | * `name` is the name of the property, and the function should fill `attrs` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6263 | * `value` with the property data. Before this callback is called, `attrs` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 6264 | * set to 0, and `value` is `V7_UNDEFINED`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6265 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6266 | * It should return non-zero if the property should be considered existing, or |
Marko Mikulicic |
0:c0ecb8bf28eb | 6267 | * zero otherwise. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6268 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6269 | * You can inspect the property attributes with the `V7_PROP_ATTR_IS_*` macros. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6270 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6271 | typedef int(v7_get_own_prop_desc_cb_t)(struct v7 *v7, v7_val_t target, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6272 | v7_val_t name, v7_prop_attr_t *attrs, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6273 | v7_val_t *value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6275 | /* Handler for `v7_mk_proxy()`; each item is a cfunction */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6276 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6277 | v7_cfunction_t *get; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6278 | v7_cfunction_t *set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6279 | v7_cfunction_t *own_keys; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6280 | v7_get_own_prop_desc_cb_t *get_own_prop_desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6281 | } v7_proxy_hnd_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6283 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6284 | * Create a Proxy object, see: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6285 | * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6286 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6287 | * Only two traps are implemented so far: `get()` and `set()`. Note that |
Marko Mikulicic |
0:c0ecb8bf28eb | 6288 | * `Object.defineProperty()` bypasses the `set()` trap. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6289 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6290 | * If `target` is not an object, the empty object will be used, so it's safe |
Marko Mikulicic |
0:c0ecb8bf28eb | 6291 | * to pass `V7_UNDEFINED` as `target`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6292 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6293 | v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6294 | const v7_proxy_hnd_t *handler); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6296 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6298 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6299 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6300 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6302 | #endif /* CS_V7_SRC_UTIL_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6303 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6304 | #line 1 "v7/src/util.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6305 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6306 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6307 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6308 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6309 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6311 | #ifndef CS_V7_SRC_UTIL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6312 | #define CS_V7_SRC_UTIL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6314 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6315 | /* Amalgamated: #include "v7/src/util_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6317 | struct bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6319 | V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6321 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 6322 | V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6323 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6324 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6325 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6326 | * At the moment, all other utility functions are public, and are declared in |
Marko Mikulicic |
0:c0ecb8bf28eb | 6327 | * `util_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6328 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6330 | #endif /* CS_V7_SRC_UTIL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6331 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6332 | #line 1 "v7/src/shdata.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6333 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6334 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6335 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6336 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6337 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6339 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6340 | * shdata (stands for "shared data") is a simple module that allows to have |
Marko Mikulicic |
0:c0ecb8bf28eb | 6341 | * reference count for an arbitrary payload data, which will be freed as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6342 | * necessary. A poor man's shared_ptr. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6343 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6345 | #ifndef CS_V7_SRC_SHDATA_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6346 | #define CS_V7_SRC_SHDATA_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6347 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6348 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6350 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6351 | struct shdata { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6352 | /* Reference count */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6353 | uint8_t refcnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6355 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6356 | * Note: we'd use `unsigned char payload[];` here, but we can't, since this |
Marko Mikulicic |
0:c0ecb8bf28eb | 6357 | * feature was introduced in C99 only |
Marko Mikulicic |
0:c0ecb8bf28eb | 6358 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6359 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6361 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6362 | * Allocate memory chunk of appropriate size, copy given `payload` data there, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6363 | * retain (`shdata_retain()`), and return it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6364 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6365 | V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6366 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6367 | V7_PRIVATE struct shdata *shdata_create_from_string(const char *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6369 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6370 | * Increment reference count for the given shared data |
Marko Mikulicic |
0:c0ecb8bf28eb | 6371 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6372 | V7_PRIVATE void shdata_retain(struct shdata *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6374 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6375 | * Decrement reference count for the given shared data |
Marko Mikulicic |
0:c0ecb8bf28eb | 6376 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6377 | V7_PRIVATE void shdata_release(struct shdata *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6379 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6380 | * Get payload data |
Marko Mikulicic |
0:c0ecb8bf28eb | 6381 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6382 | V7_PRIVATE void *shdata_get_payload(struct shdata *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6383 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6384 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6385 | #endif /* CS_V7_SRC_SHDATA_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6386 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6387 | #line 1 "v7/src/eval.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6388 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6389 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6390 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6391 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6392 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6394 | #ifndef CS_V7_SRC_EVAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6395 | #define CS_V7_SRC_EVAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6397 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6398 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6400 | struct v7_call_frame_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6402 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6403 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6404 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6406 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6407 | V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6408 | val_t this_object, uint8_t reset_line_no, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6409 | val_t *_res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6411 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6412 | V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6413 | v7_val_t args, uint8_t is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6414 | v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6415 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6416 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6417 | V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6418 | const char *filename, val_t func, val_t args, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6419 | val_t this_object, int is_json, int fr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6420 | uint8_t is_constructor, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6422 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6423 | * Try to find the call frame whose `type_mask` intersects with the given |
Marko Mikulicic |
0:c0ecb8bf28eb | 6424 | * `type_mask`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6425 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6426 | * Start from the top call frame, and go deeper until the matching frame is |
Marko Mikulicic |
0:c0ecb8bf28eb | 6427 | * found, or there's no more call frames. If the needed frame was not found, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6428 | * returns `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6429 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6430 | V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6431 | uint8_t type_mask); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6432 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6433 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6434 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6435 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6436 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6437 | #endif /* CS_V7_SRC_EVAL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6438 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6439 | #line 1 "v7/src/compiler.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6440 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6441 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6442 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6443 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6444 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6446 | #ifndef CS_V7_SRC_COMPILER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6447 | #define CS_V7_SRC_COMPILER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6449 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6450 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6451 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6453 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6455 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6456 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6457 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6459 | V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6460 | struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6462 | V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6463 | ast_off_t *ppos, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6465 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6466 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6467 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6469 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6471 | #endif /* CS_V7_SRC_COMPILER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6472 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6473 | #line 1 "v7/src/cyg_profile.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6474 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6475 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6476 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6477 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6478 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6480 | #ifndef CS_V7_SRC_CYG_PROFILE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6481 | #define CS_V7_SRC_CYG_PROFILE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6483 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6484 | * This file contains GCC/clang instrumentation callbacks, as well as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6485 | * accompanying code. The actual code in these callbacks depends on enabled |
Marko Mikulicic |
0:c0ecb8bf28eb | 6486 | * features. See cyg_profile.c for some implementation details rationale. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6487 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6489 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6491 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6493 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6494 | * Stack-tracking functionality: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6495 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6496 | * The idea is that the caller should allocate `struct stack_track_ctx` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6497 | * (typically on stack) in the function to track the stack usage of, and call |
Marko Mikulicic |
0:c0ecb8bf28eb | 6498 | * `v7_stack_track_start()` in the beginning. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6499 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6500 | * Before quitting current stack frame (for example, before returning from |
Marko Mikulicic |
0:c0ecb8bf28eb | 6501 | * function), call `v7_stack_track_end()`, which returns the maximum stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 6502 | * consumed size. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6503 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6504 | * These calls can be nested: for example, we may track the stack usage of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6505 | * whole application by using these functions in `main()`, as well as track |
Marko Mikulicic |
0:c0ecb8bf28eb | 6506 | * stack usage of any nested functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6507 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6508 | * Just to stress: both `v7_stack_track_start()` / `v7_stack_track_end()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6509 | * should be called for the same instance of `struct stack_track_ctx` in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6510 | * same stack frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6511 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6513 | /* stack tracking context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6514 | struct stack_track_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6515 | struct stack_track_ctx *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6516 | void *start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6517 | void *max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6518 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6519 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6520 | /* see explanation above */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6521 | void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6522 | /* see explanation above */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6523 | int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6525 | void v7_stack_stat_clean(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6527 | #endif /* V7_ENABLE_STACK_TRACKING */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6529 | #endif /* CS_V7_SRC_CYG_PROFILE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6530 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6531 | #line 1 "v7/builtin/builtin.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6532 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6533 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6534 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6535 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6536 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6538 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6539 | * === Non-Standard API |
Marko Mikulicic |
0:c0ecb8bf28eb | 6540 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6541 | * V7 has several non-standard extensions for `String.prototype` in |
Marko Mikulicic |
0:c0ecb8bf28eb | 6542 | * order to give a compact and fast API to access raw data obtained from |
Marko Mikulicic |
0:c0ecb8bf28eb | 6543 | * File, Socket, and hardware input/output such as I2C. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6544 | * V7 IO API functions return |
Marko Mikulicic |
0:c0ecb8bf28eb | 6545 | * string data as a result of read operations, and that string data is a |
Marko Mikulicic |
0:c0ecb8bf28eb | 6546 | * raw byte array. ECMA6 provides `ArrayBuffer` and `DataView` API for dealing |
Marko Mikulicic |
0:c0ecb8bf28eb | 6547 | * with raw bytes, because strings in JavaScript are Unicode. That standard |
Marko Mikulicic |
0:c0ecb8bf28eb | 6548 | * API is too bloated for the embedded use, and does not allow to use handy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6549 | * String API (e.g. `.match()`) against data. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6550 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6551 | * V7 internally stores strings as byte arrays. All strings created by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6552 | * String API are UTF8 encoded. Strings that are the result of |
Marko Mikulicic |
0:c0ecb8bf28eb | 6553 | * input/output API calls might not be a valid UTF8 strings, but nevertheless |
Marko Mikulicic |
0:c0ecb8bf28eb | 6554 | * they are represented as strings, and the following API allows to access |
Marko Mikulicic |
0:c0ecb8bf28eb | 6555 | * underlying byte sequence: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6556 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6557 | * ==== String.prototype.at(position) -> number or NaN |
Marko Mikulicic |
0:c0ecb8bf28eb | 6558 | * Return byte at index |
Marko Mikulicic |
0:c0ecb8bf28eb | 6559 | * `position`. Byte value is in 0,255 range. If `position` is out of bounds |
Marko Mikulicic |
0:c0ecb8bf28eb | 6560 | * (either negative or larger then the byte array length), NaN is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6561 | * Example: `"ы".at(0)` returns 0xd1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6562 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6563 | * ==== String.prototype.blen -> number |
Marko Mikulicic |
0:c0ecb8bf28eb | 6564 | * Return string length in bytes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6565 | * Example: `"ы".blen` returns 2. Note that `"ы".length` is 1, since that |
Marko Mikulicic |
0:c0ecb8bf28eb | 6566 | * string consists of a single Unicode character (2-byte). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6567 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6568 | * === Builtin API |
Marko Mikulicic |
0:c0ecb8bf28eb | 6569 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6570 | * Builtin API provides additional JavaScript interfaces available for V7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6571 | * scripts. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6572 | * File API is a wrapper around standard C calls `fopen()`, `fclose()`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6573 | * `fread()`, `fwrite()`, `rename()`, `remove()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6574 | * Crypto API provides functions for base64, md5, and sha1 encoding/decoding. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6575 | * Socket API provides low-level socket API. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6576 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6577 | * ==== File.eval(file_name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6578 | * Parse and run `file_name`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6579 | * Throws an exception if the file doesn't exist, cannot be parsed or if the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6580 | * script throws any exception. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6581 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6582 | * ==== File.read(file_name) -> string or undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 6583 | * Read file `file_name` and return a string with a file content. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6584 | * On any error, return `undefined` as a result. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6585 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6586 | * ==== File.write(file_name, str) -> true or false |
Marko Mikulicic |
0:c0ecb8bf28eb | 6587 | * Write string `str` to a file `file_name`. Return `true` on success, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6588 | * `false` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6589 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6590 | * ==== File.open(file_name [, mode]) -> file_object or null |
Marko Mikulicic |
0:c0ecb8bf28eb | 6591 | * Open a file `path`. For |
Marko Mikulicic |
0:c0ecb8bf28eb | 6592 | * list of valid `mode` values, see `fopen()` documentation. If `mode` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 6593 | * not specified, mode `rb` is used, i.e. file is opened in read-only mode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6594 | * Return an opened file object, or null on error. Example: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6595 | * `var f = File.open('/etc/passwd'); f.close();` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6596 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6597 | * ==== file_obj.close() -> undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 6598 | * Close opened file object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6599 | * NOTE: it is user's responsibility to close all opened file streams. V7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6600 | * does not do that automatically. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6601 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6602 | * ==== file_obj.read() -> string |
Marko Mikulicic |
0:c0ecb8bf28eb | 6603 | * Read portion of data from |
Marko Mikulicic |
0:c0ecb8bf28eb | 6604 | * an opened file stream. Return string with data, or empty string on EOF |
Marko Mikulicic |
0:c0ecb8bf28eb | 6605 | * or error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6606 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6607 | * ==== file_obj.write(str) -> num_bytes_written |
Marko Mikulicic |
0:c0ecb8bf28eb | 6608 | * Write string `str` to the opened file object. Return number of bytes written. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6609 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6610 | * ==== File.rename(old_name, new_name) -> errno |
Marko Mikulicic |
0:c0ecb8bf28eb | 6611 | * Rename file `old_name` to |
Marko Mikulicic |
0:c0ecb8bf28eb | 6612 | * `new_name`. Return 0 on success, or `errno` value on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6613 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6614 | * ==== File.list(dir_name) -> array_of_names |
Marko Mikulicic |
0:c0ecb8bf28eb | 6615 | * Return a list of files in a given directory, or `undefined` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6616 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6617 | * ==== File.remove(file_name) -> errno |
Marko Mikulicic |
0:c0ecb8bf28eb | 6618 | * Delete file `file_name`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6619 | * Return 0 on success, or `errno` value on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6620 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6621 | * ==== Crypto.base64_encode(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6622 | * Base64-encode input string `str` and return encoded string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6623 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6624 | * ==== Crypto.base64_decode(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6625 | * Base64-decode input string `str` and return decoded string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6626 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6627 | * ==== Crypto.md5(str), Crypto.md5_hex(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6628 | * Generate MD5 hash from input string `str`. Return 16-byte hash (`md5()`), |
Marko Mikulicic |
0:c0ecb8bf28eb | 6629 | * or stringified hexadecimal representation of the hash (`md5_hex`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6630 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6631 | * ==== Crypto.sha1(str), Crypto.sha1_hex(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6632 | * Generate SHA1 hash from input string `str`. Return 20-byte hash (`sha1()`), |
Marko Mikulicic |
0:c0ecb8bf28eb | 6633 | * or stringified hexadecimal representation of the hash (`sha1_hex`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6634 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6635 | * ==== Socket.connect(host, port [, is_udp]) -> socket_obj |
Marko Mikulicic |
0:c0ecb8bf28eb | 6636 | * Connect to a given host. `host` can be a string IP address, or a host name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6637 | * Optional `is_udp` parameter, if true, indicates that socket should be UDP. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6638 | * Return socket object on success, null on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6639 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6640 | * ==== Socket.listen(port [, ip_address [,is_udp]]) -> socket_obj |
Marko Mikulicic |
0:c0ecb8bf28eb | 6641 | * Create a listening socket on a given port. Optional `ip_address` argument |
Marko Mikulicic |
0:c0ecb8bf28eb | 6642 | * specifies and IP address to bind to. Optional `is_udp` parameter, if true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6643 | * indicates that socket should be UDP. Return socket object on success, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6644 | * null on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6645 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6646 | * ==== socket_obj.accept() -> socket_obj |
Marko Mikulicic |
0:c0ecb8bf28eb | 6647 | * Sleep until new incoming connection is arrived. Return accepted socket |
Marko Mikulicic |
0:c0ecb8bf28eb | 6648 | * object on success, or `null` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6649 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6650 | * ==== socket_obj.close() -> numeric_errno |
Marko Mikulicic |
0:c0ecb8bf28eb | 6651 | * Close socket object. Return 0 on success, or system errno on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6652 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6653 | * ==== socket_obj.recv() -> string |
Marko Mikulicic |
0:c0ecb8bf28eb | 6654 | * Read data from socket. Return data string, or empty string if peer has |
Marko Mikulicic |
0:c0ecb8bf28eb | 6655 | * disconnected, or `null` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6656 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6657 | * ==== socket_obj.recvAll() -> string |
Marko Mikulicic |
0:c0ecb8bf28eb | 6658 | * Same as `recv()`, but keeps reading data until socket is closed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6659 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6660 | * ==== sock.send(string) -> num_bytes_sent |
Marko Mikulicic |
0:c0ecb8bf28eb | 6661 | * Send string to the socket. Return number of bytes sent, or 0 on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6662 | * Simple HTTP client example: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6663 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6664 | * var s = Socket.connect("google.com", 80); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6665 | * s.send("GET / HTTP/1.0\n\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6666 | * var reply = s.recv(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6667 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6668 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6669 | #ifndef CS_V7_BUILTIN_BUILTIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6670 | #define CS_V7_BUILTIN_BUILTIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6672 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6674 | void init_file(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6675 | void init_socket(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6676 | void init_crypto(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6678 | #endif /* CS_V7_BUILTIN_BUILTIN_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6679 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6680 | #line 1 "v7/src/slre.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6681 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6682 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6683 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6684 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6685 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6686 | * This software is dual-licensed: you can redistribute it and/or modify |
Marko Mikulicic |
0:c0ecb8bf28eb | 6687 | * it under the terms of the GNU General Public License version 2 as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6688 | * published by the Free Software Foundation. For the terms of this |
Marko Mikulicic |
0:c0ecb8bf28eb | 6689 | * license, see <http://www.gnu.org/licenses/>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6690 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6691 | * You are free to use this software under the terms of the GNU General |
Marko Mikulicic |
0:c0ecb8bf28eb | 6692 | * Public License, but WITHOUT ANY WARRANTY; without even the implied |
Marko Mikulicic |
0:c0ecb8bf28eb | 6693 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6694 | * See the GNU General Public License for more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6695 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6696 | * Alternatively, you can license this software under a commercial |
Marko Mikulicic |
0:c0ecb8bf28eb | 6697 | * license, as set out in <https://www.cesanta.com/license>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6698 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6700 | #ifndef CS_V7_SRC_SLRE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6701 | #define CS_V7_SRC_SLRE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6702 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6703 | /* Return codes for slre_compile() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6704 | enum slre_error { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6705 | SLRE_OK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6706 | SLRE_INVALID_DEC_DIGIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6707 | SLRE_INVALID_HEX_DIGIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6708 | SLRE_INVALID_ESC_CHAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6709 | SLRE_UNTERM_ESC_SEQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6710 | SLRE_SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6711 | SLRE_UNMATCH_LBR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6712 | SLRE_UNMATCH_RBR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6713 | SLRE_NUM_OVERFLOW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6714 | SLRE_INF_LOOP_M_EMP_STR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6715 | SLRE_TOO_MANY_CHARSETS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6716 | SLRE_INV_CHARSET_RANGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6717 | SLRE_CHARSET_TOO_LARGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6718 | SLRE_MALFORMED_CHARSET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6719 | SLRE_INVALID_BACK_REFERENCE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6720 | SLRE_TOO_MANY_CAPTURES, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6721 | SLRE_INVALID_QUANTIFIER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6722 | SLRE_BAD_CHAR_AFTER_USD |
Marko Mikulicic |
0:c0ecb8bf28eb | 6723 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6725 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 6726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6727 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 6728 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6729 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6730 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6731 | /* Regex flags */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6732 | #define SLRE_FLAG_G 1 /* Global - match in the whole string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6733 | #define SLRE_FLAG_I 2 /* Ignore case */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6734 | #define SLRE_FLAG_M 4 /* Multiline */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6735 | #define SLRE_FLAG_RE 8 /* flag RegExp/String */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6736 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6737 | /* Describes single capture */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6738 | struct slre_cap { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6739 | const char *start; /* points to the beginning of the capture group */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6740 | const char *end; /* points to the end of the capture group */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6741 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6743 | /* Describes all captures */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6744 | #define SLRE_MAX_CAPS 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6745 | struct slre_loot { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6746 | int num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6747 | struct slre_cap caps[SLRE_MAX_CAPS]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6748 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6749 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6750 | /* Opaque structure that holds compiled regular expression */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6751 | struct slre_prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6753 | int slre_compile(const char *regexp, size_t regexp_len, const char *flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6754 | size_t flags_len, struct slre_prog **, int is_regex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6755 | int slre_exec(struct slre_prog *prog, int flag_g, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6756 | const char *end, struct slre_loot *loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6757 | void slre_free(struct slre_prog *prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6758 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6759 | int slre_match(const char *, size_t, const char *, size_t, const char *, size_t, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6760 | struct slre_loot *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6761 | int slre_replace(struct slre_loot *loot, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6762 | const char *replace, size_t rep_len, struct slre_loot *dst); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6763 | int slre_get_flags(struct slre_prog *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6764 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6765 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 6766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6767 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6768 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6769 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6770 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6771 | #endif /* CS_V7_SRC_SLRE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6772 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6773 | #line 1 "v7/src/stdlib.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6774 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6775 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6776 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6777 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6778 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6780 | #ifndef CS_V7_SRC_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6781 | #define CS_V7_SRC_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6783 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6784 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6786 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6787 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6788 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6789 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6790 | /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6792 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6793 | V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6794 | int is_json, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6796 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6797 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6798 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6799 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6800 | #endif /* CS_V7_SRC_STDLIB_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6801 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6802 | #line 1 "v7/src/heapusage.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6803 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6804 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6805 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6806 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6807 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6809 | #ifndef CS_V7_SRC_HEAPUSAGE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6810 | #define CS_V7_SRC_HEAPUSAGE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6812 | #if defined(V7_HEAPUSAGE_ENABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6813 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6814 | extern volatile int heap_dont_count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6816 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6817 | * Returns total heap-allocated size in bytes (without any overhead of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6818 | * heap implementation) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6819 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6820 | size_t heapusage_alloc_size(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6821 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6822 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6823 | * Returns number of active allocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 6824 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6825 | size_t heapusage_allocs_cnt(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6827 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6828 | * Must be called before allocating some memory that should not be indicated as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6829 | * memory consumed for some particular operation: for example, when we |
Marko Mikulicic |
0:c0ecb8bf28eb | 6830 | * preallocate some GC buffer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6831 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6832 | #define heapusage_dont_count(a) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6833 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6834 | heap_dont_count = a; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6835 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6836 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6837 | #else /* V7_HEAPUSAGE_ENABLE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6839 | #define heapusage_alloc_size() (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6840 | #define heapusage_allocs_cnt() (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6841 | #define heapusage_dont_count(a) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6843 | #endif /* V7_HEAPUSAGE_ENABLE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6844 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6845 | #endif /* CS_V7_SRC_HEAPUSAGE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6846 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6847 | #line 1 "v7/src/std_proxy.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6848 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6849 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6850 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6851 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6852 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6854 | #ifndef CS_V7_SRC_STD_PROXY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6855 | #define CS_V7_SRC_STD_PROXY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6856 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6857 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6858 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6859 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6860 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6861 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6862 | #define _V7_PROXY_TARGET_NAME "__tgt" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6863 | #define _V7_PROXY_HANDLER_NAME "__hnd" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6864 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6865 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6866 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6867 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6869 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6871 | V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6873 | V7_PRIVATE void init_proxy(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6875 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6876 | * Returns whether the given name is one of the special Proxy names |
Marko Mikulicic |
0:c0ecb8bf28eb | 6877 | * (_V7_PROXY_TARGET_NAME or _V7_PROXY_HANDLER_NAME) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6878 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6879 | V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6880 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6881 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6882 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6883 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6884 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6885 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6887 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6889 | #endif /* CS_V7_SRC_STD_PROXY_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6890 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6891 | #line 1 "v7/src/freeze.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6892 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6893 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6894 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6895 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6896 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6898 | #ifndef CS_V7_SRC_FREEZE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6899 | #define CS_V7_SRC_FREEZE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6901 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 6902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6903 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6905 | struct v7_property; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6907 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6908 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6909 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6911 | V7_PRIVATE void freeze(struct v7 *v7, char *filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6912 | V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6913 | V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6915 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6916 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6917 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6918 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6919 | #endif /* V7_FREEZE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6920 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6921 | #endif /* CS_V7_SRC_FREEZE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6922 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6923 | #line 1 "v7/src/std_array.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6924 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6925 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6926 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6927 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6928 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6930 | #ifndef CS_V7_SRC_STD_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6931 | #define CS_V7_SRC_STD_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6933 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6935 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6936 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6937 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6939 | V7_PRIVATE void init_array(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6941 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6942 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6943 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6945 | #endif /* CS_V7_SRC_STD_ARRAY_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6946 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6947 | #line 1 "v7/src/std_boolean.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6948 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6949 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6950 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6951 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6952 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6954 | #ifndef CS_V7_SRC_STD_BOOLEAN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6955 | #define CS_V7_SRC_STD_BOOLEAN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6956 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6957 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6959 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6960 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6961 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6963 | V7_PRIVATE void init_boolean(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6964 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6965 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6966 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6967 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6969 | #endif /* CS_V7_SRC_STD_BOOLEAN_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6970 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6971 | #line 1 "v7/src/std_date.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6972 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6973 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6974 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6975 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6976 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6978 | #ifndef CS_V7_SRC_STD_DATE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6979 | #define CS_V7_SRC_STD_DATE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6981 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6983 | #if V7_ENABLE__Date |
Marko Mikulicic |
0:c0ecb8bf28eb | 6984 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6985 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6986 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6987 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6989 | V7_PRIVATE void init_date(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6991 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6993 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6995 | #endif /* V7_ENABLE__Date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6996 | #endif /* CS_V7_SRC_STD_DATE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6997 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6998 | #line 1 "v7/src/std_function.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6999 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7000 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7001 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7002 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7003 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7005 | #ifndef CS_V7_SRC_STD_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7006 | #define CS_V7_SRC_STD_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7008 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7010 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7011 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7012 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7014 | V7_PRIVATE void init_function(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7015 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7016 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7017 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7018 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7020 | #endif /* CS_V7_SRC_STD_FUNCTION_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7021 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7022 | #line 1 "v7/src/std_json.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7023 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7024 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7025 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7026 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7027 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7029 | #ifndef CS_V7_SRC_STD_JSON_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7030 | #define CS_V7_SRC_STD_JSON_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7031 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7032 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7033 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7034 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7035 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7036 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7038 | V7_PRIVATE void init_json(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7040 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7041 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7042 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7043 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7044 | #endif /* CS_V7_SRC_STD_JSON_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7045 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7046 | #line 1 "v7/src/std_math.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7047 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7048 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7049 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7050 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7051 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7053 | #ifndef CS_V7_SRC_STD_MATH_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7054 | #define CS_V7_SRC_STD_MATH_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7056 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7058 | #if V7_ENABLE__Math |
Marko Mikulicic |
0:c0ecb8bf28eb | 7059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7060 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7061 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7062 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7064 | V7_PRIVATE void init_math(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7066 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7068 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7070 | #endif /* V7_ENABLE__Math */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7071 | #endif /* CS_V7_SRC_STD_MATH_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7072 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7073 | #line 1 "v7/src/std_number.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7074 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7075 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7076 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7077 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7078 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7079 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7080 | #ifndef CS_V7_SRC_STD_NUMBER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7081 | #define CS_V7_SRC_STD_NUMBER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7083 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7085 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7086 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7087 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7088 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7089 | V7_PRIVATE void init_number(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7091 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7093 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7095 | #endif /* CS_V7_SRC_STD_NUMBER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7096 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7097 | #line 1 "v7/src/std_object.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7098 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7099 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7100 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7101 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7102 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7104 | #ifndef CS_V7_SRC_STD_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7105 | #define CS_V7_SRC_STD_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7106 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7107 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7108 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7110 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7112 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7113 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7114 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7115 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7116 | V7_PRIVATE void init_object(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7117 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7118 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 7119 | V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7121 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7122 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7123 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7125 | #endif /* CS_V7_SRC_STD_OBJECT_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7126 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7127 | #line 1 "v7/src/std_regex.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7128 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7129 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7130 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7131 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7132 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7134 | #ifndef CS_V7_SRC_STD_REGEX_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7135 | #define CS_V7_SRC_STD_REGEX_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7136 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7137 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7138 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7140 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 7141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7142 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7143 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7144 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7146 | V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7147 | V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, v7_val_t rx, v7_val_t vstr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7148 | int lind, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7150 | V7_PRIVATE void init_regex(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7151 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7152 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7153 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7154 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7156 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7158 | #endif /* CS_V7_SRC_STD_REGEX_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7159 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7160 | #line 1 "v7/src/std_string.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7161 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7162 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7163 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7164 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7165 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7167 | #ifndef CS_V7_SRC_STD_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7168 | #define CS_V7_SRC_STD_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7170 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7171 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7173 | /* Max captures for String.replace() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7174 | #define V7_RE_MAX_REPL_SUB 20 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7175 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7176 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7177 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7178 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7180 | V7_PRIVATE void init_string(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7182 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7183 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7184 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7186 | #endif /* CS_V7_SRC_STD_STRING_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7187 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7188 | #line 1 "v7/src/js_stdlib.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7189 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7190 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7191 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7192 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7193 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7195 | #ifndef CS_V7_SRC_JS_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7196 | #define CS_V7_SRC_JS_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7198 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7199 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7200 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7201 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7202 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7204 | V7_PRIVATE void init_js_stdlib(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7205 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7206 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7207 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7208 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7210 | #endif /* CS_V7_SRC_JS_STDLIB_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7211 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7212 | #line 1 "v7/src/main_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7213 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7214 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7215 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7216 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7217 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7218 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7219 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7220 | * === v7 main() |
Marko Mikulicic |
0:c0ecb8bf28eb | 7221 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7223 | #ifndef CS_V7_SRC_MAIN_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7224 | #define CS_V7_SRC_MAIN_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7226 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7228 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7229 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7230 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7232 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7233 | * V7 executable main function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7234 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 7235 | * There are various callbacks available: |
Marko Mikulicic |
0:c0ecb8bf28eb | 7236 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 7237 | * `pre_freeze_init()` and `pre_init()` are optional intialization functions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7238 | * aimed to export any extra functionality into vanilla v7 engine. They are |
Marko Mikulicic |
0:c0ecb8bf28eb | 7239 | * called after v7 initialization, before executing given files or inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 7240 | * expressions. `pre_freeze_init()` is called before "freezing" v7 state; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7241 | * whereas `pre_init` called afterwards. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7242 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 7243 | * `post_init()`, if provided, is called after executing files and expressions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7244 | * before destroying v7 instance and exiting. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7245 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7246 | int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7247 | void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7249 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7251 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7253 | #endif /* CS_V7_SRC_MAIN_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7254 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7255 | #line 1 "v7/src/main.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7256 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7257 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7258 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7259 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7260 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7262 | #ifndef CS_V7_SRC_MAIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7263 | #define CS_V7_SRC_MAIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7264 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7265 | /* Amalgamated: #include "v7/src/main_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7267 | #endif /* CS_V7_SRC_MAIN_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7268 | #ifndef V7_EXPORT_INTERNAL_HEADERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 7269 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7270 | #line 1 "common/mbuf.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7271 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7272 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7273 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7274 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7275 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7277 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 7278 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7279 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7280 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7281 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7283 | #ifndef MBUF_REALLOC |
Marko Mikulicic |
0:c0ecb8bf28eb | 7284 | #define MBUF_REALLOC realloc |
Marko Mikulicic |
0:c0ecb8bf28eb | 7285 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7286 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7287 | #ifndef MBUF_FREE |
Marko Mikulicic |
0:c0ecb8bf28eb | 7288 | #define MBUF_FREE free |
Marko Mikulicic |
0:c0ecb8bf28eb | 7289 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7290 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7291 | void mbuf_init(struct mbuf *mbuf, size_t initial_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7292 | mbuf->len = mbuf->size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7293 | mbuf->buf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7294 | mbuf_resize(mbuf, initial_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7297 | void mbuf_free(struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7298 | if (mbuf->buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7299 | MBUF_FREE(mbuf->buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7300 | mbuf_init(mbuf, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7302 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7303 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7304 | void mbuf_resize(struct mbuf *a, size_t new_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7305 | if (new_size > a->size || (new_size < a->size && new_size >= a->len)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7306 | char *buf = (char *) MBUF_REALLOC(a->buf, new_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7307 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7308 | * In case realloc fails, there's not much we can do, except keep things as |
Marko Mikulicic |
0:c0ecb8bf28eb | 7309 | * they are. Note that NULL is a valid return value from realloc when |
Marko Mikulicic |
0:c0ecb8bf28eb | 7310 | * size == 0, but that is covered too. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7311 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7312 | if (buf == NULL && new_size != 0) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7313 | a->buf = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7314 | a->size = new_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7315 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7316 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7318 | void mbuf_trim(struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7319 | mbuf_resize(mbuf, mbuf->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7322 | size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7323 | char *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7324 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7325 | assert(a != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7326 | assert(a->len <= a->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7327 | assert(off <= a->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7328 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7329 | /* check overflow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7330 | if (~(size_t) 0 - (size_t) a->buf < len) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7332 | if (a->len + len <= a->size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7333 | memmove(a->buf + off + len, a->buf + off, a->len - off); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7334 | if (buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7335 | memcpy(a->buf + off, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7336 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7337 | a->len += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7338 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7339 | size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7340 | if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7341 | a->buf = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7342 | memmove(a->buf + off + len, a->buf + off, a->len - off); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7343 | if (buf != NULL) memcpy(a->buf + off, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7344 | a->len += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7345 | a->size = new_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7346 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7347 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7348 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7349 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7351 | return len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7352 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7354 | size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7355 | return mbuf_insert(a, a->len, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7356 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7358 | void mbuf_remove(struct mbuf *mb, size_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7359 | if (n > 0 && n <= mb->len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7360 | memmove(mb->buf, mb->buf + n, mb->len - n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7361 | mb->len -= n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7362 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7365 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7366 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7367 | #line 1 "common/str_util.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7368 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7369 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7370 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7371 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7372 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7374 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 7375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7376 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7377 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7379 | size_t c_strnlen(const char *s, size_t maxlen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7380 | size_t l = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7381 | for (; l < maxlen && s[l] != '\0'; l++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7382 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7383 | return l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7384 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7386 | #define C_SNPRINTF_APPEND_CHAR(ch) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7387 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7388 | if (i < (int) buf_size) buf[i] = ch; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7389 | i++; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7390 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7391 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7392 | #define C_SNPRINTF_FLAG_ZERO 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7394 | #ifdef C_DISABLE_BUILTIN_SNPRINTF |
Marko Mikulicic |
0:c0ecb8bf28eb | 7395 | int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7396 | return vsnprintf(buf, buf_size, fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7397 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7398 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 7399 | static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7400 | int field_width) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7401 | char tmp[40]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7402 | int i = 0, k = 0, neg = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7403 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7404 | if (num < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7405 | neg++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7406 | num = -num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7409 | /* Print into temporary buffer - in reverse order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7410 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7411 | int rem = num % base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7412 | if (rem < 10) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7413 | tmp[k++] = '0' + rem; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7414 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7415 | tmp[k++] = 'a' + (rem - 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7417 | num /= base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7418 | } while (num > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7419 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7420 | /* Zero padding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7421 | if (flags && C_SNPRINTF_FLAG_ZERO) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7422 | while (k < field_width && k < (int) sizeof(tmp) - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7423 | tmp[k++] = '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7424 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7425 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7427 | /* And sign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7428 | if (neg) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7429 | tmp[k++] = '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7430 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7432 | /* Now output */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7433 | while (--k >= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7434 | C_SNPRINTF_APPEND_CHAR(tmp[k]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7435 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7436 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7437 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7438 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7440 | int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7441 | int ch, i = 0, len_mod, flags, precision, field_width; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7443 | while ((ch = *fmt++) != '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7444 | if (ch != '%') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7445 | C_SNPRINTF_APPEND_CHAR(ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7446 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7447 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7448 | * Conversion specification: |
Marko Mikulicic |
0:c0ecb8bf28eb | 7449 | * zero or more flags (one of: # 0 - <space> + ') |
Marko Mikulicic |
0:c0ecb8bf28eb | 7450 | * an optional minimum field width (digits) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7451 | * an optional precision (. followed by digits, or *) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7452 | * an optional length modifier (one of: hh h l ll L q j z t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7453 | * conversion specifier (one of: d i o u x X e E f F g G a A c s p n) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7454 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7455 | flags = field_width = precision = len_mod = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7457 | /* Flags. only zero-pad flag is supported. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7458 | if (*fmt == '0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7459 | flags |= C_SNPRINTF_FLAG_ZERO; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7462 | /* Field width */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7463 | while (*fmt >= '0' && *fmt <= '9') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7464 | field_width *= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7465 | field_width += *fmt++ - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7466 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7467 | /* Dynamic field width */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7468 | if (*fmt == '*') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7469 | field_width = va_arg(ap, int); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7470 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7471 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7473 | /* Precision */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7474 | if (*fmt == '.') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7475 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7476 | if (*fmt == '*') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7477 | precision = va_arg(ap, int); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7478 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7479 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7480 | while (*fmt >= '0' && *fmt <= '9') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7481 | precision *= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7482 | precision += *fmt++ - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7483 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7484 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7485 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7486 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7487 | /* Length modifier */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7488 | switch (*fmt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7489 | case 'h': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7490 | case 'l': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7491 | case 'L': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7492 | case 'I': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7493 | case 'q': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7494 | case 'j': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7495 | case 'z': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7496 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7497 | len_mod = *fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7498 | if (*fmt == 'h') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7499 | len_mod = 'H'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7500 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7501 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7502 | if (*fmt == 'l') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7503 | len_mod = 'q'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7504 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7505 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7506 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7507 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7509 | ch = *fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7510 | if (ch == 's') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7511 | const char *s = va_arg(ap, const char *); /* Always fetch parameter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7512 | int j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7513 | int pad = field_width - (precision >= 0 ? c_strnlen(s, precision) : 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7514 | for (j = 0; j < pad; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7515 | C_SNPRINTF_APPEND_CHAR(' '); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7516 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7518 | /* `s` may be NULL in case of %.*s */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7519 | if (s != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7520 | /* Ignore negative and 0 precisions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7521 | for (j = 0; (precision <= 0 || j < precision) && s[j] != '\0'; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7522 | C_SNPRINTF_APPEND_CHAR(s[j]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7525 | } else if (ch == 'c') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7526 | ch = va_arg(ap, int); /* Always fetch parameter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7527 | C_SNPRINTF_APPEND_CHAR(ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7528 | } else if (ch == 'd' && len_mod == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7529 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, int), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7530 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7531 | } else if (ch == 'd' && len_mod == 'l') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7532 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, long), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7533 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7534 | #ifdef SSIZE_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 7535 | } else if (ch == 'd' && len_mod == 'z') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7536 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, ssize_t), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7537 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7538 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7539 | } else if (ch == 'd' && len_mod == 'q') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7540 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, int64_t), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7541 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7542 | } else if ((ch == 'x' || ch == 'u') && len_mod == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7543 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7544 | ch == 'x' ? 16 : 10, flags, field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7545 | } else if ((ch == 'x' || ch == 'u') && len_mod == 'l') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7546 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned long), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7547 | ch == 'x' ? 16 : 10, flags, field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7548 | } else if ((ch == 'x' || ch == 'u') && len_mod == 'z') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7549 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, size_t), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7550 | ch == 'x' ? 16 : 10, flags, field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7551 | } else if (ch == 'p') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7552 | unsigned long num = (unsigned long) (uintptr_t) va_arg(ap, void *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7553 | C_SNPRINTF_APPEND_CHAR('0'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7554 | C_SNPRINTF_APPEND_CHAR('x'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7555 | i += c_itoa(buf + i, buf_size - i, num, 16, flags, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7556 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7557 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 7558 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7559 | * TODO(lsm): abort is not nice in a library, remove it |
Marko Mikulicic |
0:c0ecb8bf28eb | 7560 | * Also, ESP8266 SDK doesn't have it |
Marko Mikulicic |
0:c0ecb8bf28eb | 7561 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7562 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7563 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7564 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7565 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7566 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7567 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7568 | /* Zero-terminate the result */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7569 | if (buf_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7570 | buf[i < (int) buf_size ? i : (int) buf_size - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7571 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7573 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7574 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7575 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7576 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7577 | int c_snprintf(char *buf, size_t buf_size, const char *fmt, ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7578 | int result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7579 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7580 | va_start(ap, fmt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7581 | result = c_vsnprintf(buf, buf_size, fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7582 | va_end(ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7583 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7584 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7586 | #ifdef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7587 | int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7588 | int ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7589 | char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7591 | strncpy(buf, path, sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7592 | buf[sizeof(buf) - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7594 | /* Trim trailing slashes. Leave backslash for paths like "X:\" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7595 | p = buf + strlen(buf) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7596 | while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7597 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7598 | memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7599 | ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7601 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7602 | * Convert back to Unicode. If doubly-converted string does not match the |
Marko Mikulicic |
0:c0ecb8bf28eb | 7603 | * original, something is fishy, reject. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7604 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7605 | WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7606 | NULL, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7607 | if (strcmp(buf, buf2) != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7608 | wbuf[0] = L'\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7609 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7610 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7612 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7613 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7614 | #endif /* _WIN32 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7616 | /* The simplest O(mn) algorithm. Better implementation are GPLed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7617 | const char *c_strnstr(const char *s, const char *find, size_t slen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7618 | size_t find_length = strlen(find); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7619 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7621 | for (i = 0; i < slen; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7622 | if (i + find_length > slen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7623 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7624 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7626 | if (strncmp(&s[i], find, find_length) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7627 | return &s[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7628 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7629 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7630 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7631 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7634 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7635 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7636 | #line 1 "common/utf.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7637 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7638 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7639 | * The authors of this software are Rob Pike and Ken Thompson. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7640 | * Copyright (c) 2002 by Lucent Technologies. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7641 | * Permission to use, copy, modify, and distribute this software for any |
Marko Mikulicic |
0:c0ecb8bf28eb | 7642 | * purpose without fee is hereby granted, provided that this entire notice |
Marko Mikulicic |
0:c0ecb8bf28eb | 7643 | * is included in all copies of any software which is or includes a copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 7644 | * or modification of this software and in all copies of the supporting |
Marko Mikulicic |
0:c0ecb8bf28eb | 7645 | * documentation for such software. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7646 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED |
Marko Mikulicic |
0:c0ecb8bf28eb | 7647 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE |
Marko Mikulicic |
0:c0ecb8bf28eb | 7648 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 7649 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7650 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7652 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 7653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7654 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7656 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7657 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7658 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7659 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7661 | #if CS_ENABLE_UTF8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7662 | enum { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7663 | Bit1 = 7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7664 | Bitx = 6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7665 | Bit2 = 5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7666 | Bit3 = 4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7667 | Bit4 = 3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7668 | Bit5 = 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7670 | T1 = ((1 << (Bit1 + 1)) - 1) ^ 0xFF, /* 0000 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7671 | Tx = ((1 << (Bitx + 1)) - 1) ^ 0xFF, /* 1000 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7672 | T2 = ((1 << (Bit2 + 1)) - 1) ^ 0xFF, /* 1100 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7673 | T3 = ((1 << (Bit3 + 1)) - 1) ^ 0xFF, /* 1110 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7674 | T4 = ((1 << (Bit4 + 1)) - 1) ^ 0xFF, /* 1111 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7675 | T5 = ((1 << (Bit5 + 1)) - 1) ^ 0xFF, /* 1111 1000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7676 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7677 | Rune1 = (1 << (Bit1 + 0 * Bitx)) - 1, /* 0000 0000 0000 0000 0111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7678 | Rune2 = (1 << (Bit2 + 1 * Bitx)) - 1, /* 0000 0000 0000 0111 1111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7679 | Rune3 = (1 << (Bit3 + 2 * Bitx)) - 1, /* 0000 0000 1111 1111 1111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7680 | Rune4 = (1 << (Bit4 + 3 * Bitx)) - 1, /* 0011 1111 1111 1111 1111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7682 | Maskx = (1 << Bitx) - 1, /* 0011 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7683 | Testx = Maskx ^ 0xFF, /* 1100 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7684 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7685 | Bad = Runeerror |
Marko Mikulicic |
0:c0ecb8bf28eb | 7686 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7687 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7688 | int chartorune(Rune *rune, const char *str) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7689 | int c, c1, c2 /* , c3 */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7690 | unsigned short l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7692 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7693 | * one character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7694 | * 00000-0007F => T1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7695 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7696 | c = *(uchar *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7697 | if (c < Tx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7698 | *rune = c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7699 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7700 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7702 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7703 | * two character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7704 | * 0080-07FF => T2 Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7705 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7706 | c1 = *(uchar *) (str + 1) ^ Tx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7707 | if (c1 & Testx) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7708 | if (c < T3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7709 | if (c < T2) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7710 | l = ((c << Bitx) | c1) & Rune2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7711 | if (l <= Rune1) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7712 | *rune = l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7713 | return 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7714 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7716 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7717 | * three character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7718 | * 0800-FFFF => T3 Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7719 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7720 | c2 = *(uchar *) (str + 2) ^ Tx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7721 | if (c2 & Testx) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7722 | if (c < T4) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7723 | l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7724 | if (l <= Rune2) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7725 | *rune = l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7726 | return 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7727 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7729 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7730 | * four character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7731 | * 10000-10FFFF => T4 Tx Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7732 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7733 | /* if(UTFmax >= 4) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7734 | c3 = *(uchar*)(str+3) ^ Tx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7735 | if(c3 & Testx) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7736 | goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7737 | if(c < T5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7738 | l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & |
Marko Mikulicic |
0:c0ecb8bf28eb | 7739 | Rune4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7740 | if(l <= Rune3) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7741 | goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7742 | if(l > Runemax) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7743 | goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7744 | *rune = l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7745 | return 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7746 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7747 | } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7749 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7750 | * bad decoding |
Marko Mikulicic |
0:c0ecb8bf28eb | 7751 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7752 | bad: |
Marko Mikulicic |
0:c0ecb8bf28eb | 7753 | *rune = Bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7754 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7755 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7756 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7757 | int runetochar(char *str, Rune *rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7758 | unsigned short c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7760 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7761 | * one character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7762 | * 00000-0007F => 00-7F |
Marko Mikulicic |
0:c0ecb8bf28eb | 7763 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7764 | c = *rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7765 | if (c <= Rune1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7766 | str[0] = c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7767 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7768 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7770 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7771 | * two character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7772 | * 00080-007FF => T2 Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7773 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7774 | if (c <= Rune2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7775 | str[0] = T2 | (c >> 1 * Bitx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7776 | str[1] = Tx | (c & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7777 | return 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7778 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7780 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7781 | * three character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7782 | * 00800-0FFFF => T3 Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7783 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7784 | /* if(c > Runemax) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7785 | c = Runeerror; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7786 | /* if(c <= Rune3) { */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7787 | str[0] = T3 | (c >> 2 * Bitx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7788 | str[1] = Tx | ((c >> 1 * Bitx) & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7789 | str[2] = Tx | (c & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7790 | return 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7791 | /* } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7793 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7794 | * four character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7795 | * 010000-1FFFFF => T4 Tx Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7796 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7797 | /* str[0] = T4 | (c >> 3*Bitx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7798 | str[1] = Tx | ((c >> 2*Bitx) & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7799 | str[2] = Tx | ((c >> 1*Bitx) & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7800 | str[3] = Tx | (c & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7801 | return 4; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7804 | int fullrune(const char *str, int n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7805 | int c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7806 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7807 | if (n <= 0) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7808 | c = *(uchar *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7809 | if (c < Tx) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7810 | if (c < T3) return n >= 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7811 | if (UTFmax == 3 || c < T4) return n >= 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7812 | return n >= 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7813 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7815 | int utfnlen(const char *s, long m) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7816 | int c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7817 | long n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7818 | Rune rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7819 | const char *es; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7821 | es = s + m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7822 | for (n = 0; s < es; n++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7823 | c = *(uchar *) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7824 | if (c < Runeself) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7825 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7826 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7828 | if (!fullrune(s, es - s)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7829 | s += chartorune(&rune, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7830 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7831 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7832 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7834 | const char *utfnshift(const char *s, long m) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7835 | int c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7836 | long n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7837 | Rune rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7839 | for (n = 0; n < m; n++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7840 | c = *(uchar *) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7841 | if (c < Runeself) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7842 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7843 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7845 | s += chartorune(&rune, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7847 | return s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7848 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7850 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7851 | * The authors of this software are Rob Pike and Ken Thompson. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7852 | * Copyright (c) 2002 by Lucent Technologies. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7853 | * Permission to use, copy, modify, and distribute this software for any |
Marko Mikulicic |
0:c0ecb8bf28eb | 7854 | * purpose without fee is hereby granted, provided that this entire notice |
Marko Mikulicic |
0:c0ecb8bf28eb | 7855 | * is included in all copies of any software which is or includes a copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 7856 | * or modification of this software and in all copies of the supporting |
Marko Mikulicic |
0:c0ecb8bf28eb | 7857 | * documentation for such software. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7858 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED |
Marko Mikulicic |
0:c0ecb8bf28eb | 7859 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE |
Marko Mikulicic |
0:c0ecb8bf28eb | 7860 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 7861 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7862 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7863 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7864 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7865 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7867 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7868 | * alpha ranges - |
Marko Mikulicic |
0:c0ecb8bf28eb | 7869 | * only covers ranges not in lower||upper |
Marko Mikulicic |
0:c0ecb8bf28eb | 7870 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7871 | static Rune __alpha2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7872 | 0x00d8, 0x00f6, /* Ø - ö */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7873 | 0x00f8, 0x01f5, /* ø - ǵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7874 | 0x0250, 0x02a8, /* ɐ - ʨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7875 | 0x038e, 0x03a1, /* Ύ - Ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7876 | 0x03a3, 0x03ce, /* Σ - ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7877 | 0x03d0, 0x03d6, /* ϐ - ϖ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7878 | 0x03e2, 0x03f3, /* Ϣ - ϳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7879 | 0x0490, 0x04c4, /* Ґ - ӄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7880 | 0x0561, 0x0587, /* ա - և */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7881 | 0x05d0, 0x05ea, /* א - ת */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7882 | 0x05f0, 0x05f2, /* װ - ײ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7883 | 0x0621, 0x063a, /* ء - غ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7884 | 0x0640, 0x064a, /* ـ - ي */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7885 | 0x0671, 0x06b7, /* ٱ - ڷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7886 | 0x06ba, 0x06be, /* ں - ھ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7887 | 0x06c0, 0x06ce, /* ۀ - ێ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7888 | 0x06d0, 0x06d3, /* ې - ۓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7889 | 0x0905, 0x0939, /* अ - ह */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7890 | 0x0958, 0x0961, /* क़ - ॡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7891 | 0x0985, 0x098c, /* অ - ঌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7892 | 0x098f, 0x0990, /* এ - ঐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7893 | 0x0993, 0x09a8, /* ও - ন */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7894 | 0x09aa, 0x09b0, /* প - র */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7895 | 0x09b6, 0x09b9, /* শ - হ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7896 | 0x09dc, 0x09dd, /* ড় - ঢ় */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7897 | 0x09df, 0x09e1, /* য় - ৡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7898 | 0x09f0, 0x09f1, /* ৰ - ৱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7899 | 0x0a05, 0x0a0a, /* ਅ - ਊ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7900 | 0x0a0f, 0x0a10, /* ਏ - ਐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7901 | 0x0a13, 0x0a28, /* ਓ - ਨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7902 | 0x0a2a, 0x0a30, /* ਪ - ਰ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7903 | 0x0a32, 0x0a33, /* ਲ - ਲ਼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7904 | 0x0a35, 0x0a36, /* ਵ - ਸ਼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7905 | 0x0a38, 0x0a39, /* ਸ - ਹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7906 | 0x0a59, 0x0a5c, /* ਖ਼ - ੜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7907 | 0x0a85, 0x0a8b, /* અ - ઋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7908 | 0x0a8f, 0x0a91, /* એ - ઑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7909 | 0x0a93, 0x0aa8, /* ઓ - ન */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7910 | 0x0aaa, 0x0ab0, /* પ - ર */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7911 | 0x0ab2, 0x0ab3, /* લ - ળ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7912 | 0x0ab5, 0x0ab9, /* વ - હ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7913 | 0x0b05, 0x0b0c, /* ଅ - ଌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7914 | 0x0b0f, 0x0b10, /* ଏ - ଐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7915 | 0x0b13, 0x0b28, /* ଓ - ନ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7916 | 0x0b2a, 0x0b30, /* ପ - ର */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7917 | 0x0b32, 0x0b33, /* ଲ - ଳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7918 | 0x0b36, 0x0b39, /* ଶ - ହ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7919 | 0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7920 | 0x0b5f, 0x0b61, /* ୟ - ୡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7921 | 0x0b85, 0x0b8a, /* அ - ஊ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7922 | 0x0b8e, 0x0b90, /* எ - ஐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7923 | 0x0b92, 0x0b95, /* ஒ - க */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7924 | 0x0b99, 0x0b9a, /* ங - ச */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7925 | 0x0b9e, 0x0b9f, /* ஞ - ட */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7926 | 0x0ba3, 0x0ba4, /* ண - த */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7927 | 0x0ba8, 0x0baa, /* ந - ப */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7928 | 0x0bae, 0x0bb5, /* ம - வ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7929 | 0x0bb7, 0x0bb9, /* ஷ - ஹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7930 | 0x0c05, 0x0c0c, /* అ - ఌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7931 | 0x0c0e, 0x0c10, /* ఎ - ఐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7932 | 0x0c12, 0x0c28, /* ఒ - న */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7933 | 0x0c2a, 0x0c33, /* ప - ళ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7934 | 0x0c35, 0x0c39, /* వ - హ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7935 | 0x0c60, 0x0c61, /* ౠ - ౡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7936 | 0x0c85, 0x0c8c, /* ಅ - ಌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7937 | 0x0c8e, 0x0c90, /* ಎ - ಐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7938 | 0x0c92, 0x0ca8, /* ಒ - ನ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7939 | 0x0caa, 0x0cb3, /* ಪ - ಳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7940 | 0x0cb5, 0x0cb9, /* ವ - ಹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7941 | 0x0ce0, 0x0ce1, /* ೠ - ೡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7942 | 0x0d05, 0x0d0c, /* അ - ഌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7943 | 0x0d0e, 0x0d10, /* എ - ഐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7944 | 0x0d12, 0x0d28, /* ഒ - ന */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7945 | 0x0d2a, 0x0d39, /* പ - ഹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7946 | 0x0d60, 0x0d61, /* ൠ - ൡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7947 | 0x0e01, 0x0e30, /* ก - ะ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7948 | 0x0e32, 0x0e33, /* า - ำ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7949 | 0x0e40, 0x0e46, /* เ - ๆ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7950 | 0x0e5a, 0x0e5b, /* ๚ - ๛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7951 | 0x0e81, 0x0e82, /* ກ - ຂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7952 | 0x0e87, 0x0e88, /* ງ - ຈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7953 | 0x0e94, 0x0e97, /* ດ - ທ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7954 | 0x0e99, 0x0e9f, /* ນ - ຟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7955 | 0x0ea1, 0x0ea3, /* ມ - ຣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7956 | 0x0eaa, 0x0eab, /* ສ - ຫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7957 | 0x0ead, 0x0eae, /* ອ - ຮ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7958 | 0x0eb2, 0x0eb3, /* າ - ຳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7959 | 0x0ec0, 0x0ec4, /* ເ - ໄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7960 | 0x0edc, 0x0edd, /* ໜ - ໝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7961 | 0x0f18, 0x0f19, /* ༘ - ༙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7962 | 0x0f40, 0x0f47, /* ཀ - ཇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7963 | 0x0f49, 0x0f69, /* ཉ - ཀྵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7964 | 0x10d0, 0x10f6, /* ა - ჶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7965 | 0x1100, 0x1159, /* ᄀ - ᅙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7966 | 0x115f, 0x11a2, /* ᅟ - ᆢ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7967 | 0x11a8, 0x11f9, /* ᆨ - ᇹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7968 | 0x1e00, 0x1e9b, /* Ḁ - ẛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7969 | 0x1f50, 0x1f57, /* ὐ - ὗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7970 | 0x1f80, 0x1fb4, /* ᾀ - ᾴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7971 | 0x1fb6, 0x1fbc, /* ᾶ - ᾼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7972 | 0x1fc2, 0x1fc4, /* ῂ - ῄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7973 | 0x1fc6, 0x1fcc, /* ῆ - ῌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7974 | 0x1fd0, 0x1fd3, /* ῐ - ΐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7975 | 0x1fd6, 0x1fdb, /* ῖ - Ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7976 | 0x1fe0, 0x1fec, /* ῠ - Ῥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7977 | 0x1ff2, 0x1ff4, /* ῲ - ῴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7978 | 0x1ff6, 0x1ffc, /* ῶ - ῼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7979 | 0x210a, 0x2113, /* ℊ - ℓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7980 | 0x2115, 0x211d, /* ℕ - ℝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7981 | 0x2120, 0x2122, /* ℠ - ™ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7982 | 0x212a, 0x2131, /* K - ℱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7983 | 0x2133, 0x2138, /* ℳ - ℸ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7984 | 0x3041, 0x3094, /* ぁ - ゔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7985 | 0x30a1, 0x30fa, /* ァ - ヺ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7986 | 0x3105, 0x312c, /* ㄅ - ㄬ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7987 | 0x3131, 0x318e, /* ㄱ - ㆎ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7988 | 0x3192, 0x319f, /* ㆒ - ㆟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7989 | 0x3260, 0x327b, /* ㉠ - ㉻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7990 | 0x328a, 0x32b0, /* ㊊ - ㊰ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7991 | 0x32d0, 0x32fe, /* ㋐ - ㋾ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7992 | 0x3300, 0x3357, /* ㌀ - ㍗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7993 | 0x3371, 0x3376, /* ㍱ - ㍶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7994 | 0x337b, 0x3394, /* ㍻ - ㎔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7995 | 0x3399, 0x339e, /* ㎙ - ㎞ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7996 | 0x33a9, 0x33ad, /* ㎩ - ㎭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7997 | 0x33b0, 0x33c1, /* ㎰ - ㏁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7998 | 0x33c3, 0x33c5, /* ㏃ - ㏅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7999 | 0x33c7, 0x33d7, /* ㏇ - ㏗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8000 | 0x33d9, 0x33dd, /* ㏙ - ㏝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8001 | 0x4e00, 0x9fff, /* 一 - 鿿 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8002 | 0xac00, 0xd7a3, /* 가 - 힣 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8003 | 0xf900, 0xfb06, /* 豈 - st */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8004 | 0xfb13, 0xfb17, /* ﬓ - ﬗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8005 | 0xfb1f, 0xfb28, /* ײַ - ﬨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8006 | 0xfb2a, 0xfb36, /* שׁ - זּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8007 | 0xfb38, 0xfb3c, /* טּ - לּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8008 | 0xfb40, 0xfb41, /* נּ - סּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8009 | 0xfb43, 0xfb44, /* ףּ - פּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8010 | 0xfb46, 0xfbb1, /* צּ - ﮱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8011 | 0xfbd3, 0xfd3d, /* ﯓ - ﴽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8012 | 0xfd50, 0xfd8f, /* ﵐ - ﶏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8013 | 0xfd92, 0xfdc7, /* ﶒ - ﷇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8014 | 0xfdf0, 0xfdf9, /* ﷰ - ﷹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8015 | 0xfe70, 0xfe72, /* ﹰ - ﹲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8016 | 0xfe76, 0xfefc, /* ﹶ - ﻼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8017 | 0xff66, 0xff6f, /* ヲ - ッ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8018 | 0xff71, 0xff9d, /* ア - ン */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8019 | 0xffa0, 0xffbe, /* ᅠ - ᄒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8020 | 0xffc2, 0xffc7, /* ᅡ - ᅦ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8021 | 0xffca, 0xffcf, /* ᅧ - ᅬ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8022 | 0xffd2, 0xffd7, /* ᅭ - ᅲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8023 | 0xffda, 0xffdc, /* ᅳ - ᅵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8024 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8026 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8027 | * alpha singlets - |
Marko Mikulicic |
0:c0ecb8bf28eb | 8028 | * only covers ranges not in lower||upper |
Marko Mikulicic |
0:c0ecb8bf28eb | 8029 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8030 | static Rune __alpha1[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8031 | 0x00aa, /* ª */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8032 | 0x00b5, /* µ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8033 | 0x00ba, /* º */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8034 | 0x03da, /* Ϛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8035 | 0x03dc, /* Ϝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8036 | 0x03de, /* Ϟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8037 | 0x03e0, /* Ϡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8038 | 0x06d5, /* ە */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8039 | 0x09b2, /* ল */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8040 | 0x0a5e, /* ਫ਼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8041 | 0x0a8d, /* ઍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8042 | 0x0ae0, /* ૠ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8043 | 0x0b9c, /* ஜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8044 | 0x0cde, /* ೞ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8045 | 0x0e4f, /* ๏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8046 | 0x0e84, /* ຄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8047 | 0x0e8a, /* ຊ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8048 | 0x0e8d, /* ຍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8049 | 0x0ea5, /* ລ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8050 | 0x0ea7, /* ວ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8051 | 0x0eb0, /* ະ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8052 | 0x0ebd, /* ຽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8053 | 0x1fbe, /* ι */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8054 | 0x207f, /* ⁿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8055 | 0x20a8, /* ₨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8056 | 0x2102, /* ℂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8057 | 0x2107, /* ℇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8058 | 0x2124, /* ℤ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8059 | 0x2126, /* Ω */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8060 | 0x2128, /* ℨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8061 | 0xfb3e, /* מּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8062 | 0xfe74, /* ﹴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8063 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8065 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8066 | * space ranges |
Marko Mikulicic |
0:c0ecb8bf28eb | 8067 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8068 | static Rune __space2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8069 | 0x0009, 0x000a, /* tab and newline */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8070 | 0x0020, 0x0020, /* space */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8071 | 0x00a0, 0x00a0, /* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8072 | 0x2000, 0x200b, /* - */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8073 | 0x2028, 0x2029, /* - */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8074 | 0x3000, 0x3000, /* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8075 | 0xfeff, 0xfeff, /* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8076 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8078 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8079 | * lower case ranges |
Marko Mikulicic |
0:c0ecb8bf28eb | 8080 | * 3rd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8081 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8082 | static Rune __toupper2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8083 | 0x0061, 0x007a, 468, /* a-z A-Z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8084 | 0x00e0, 0x00f6, 468, /* à-ö À-Ö */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8085 | 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8086 | 0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8087 | 0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8088 | 0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8089 | 0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8090 | 0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8091 | 0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8092 | 0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8093 | 0x0430, 0x044f, 468, /* а-я А-Я */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8094 | 0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8095 | 0x045e, 0x045f, 420, /* ў-џ Ў-Џ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8096 | 0x0561, 0x0586, 452, /* ա-ֆ Ա-Ֆ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8097 | 0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8098 | 0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8099 | 0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8100 | 0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8101 | 0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8102 | 0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8103 | 0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8104 | 0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8105 | 0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8106 | 0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8107 | 0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8108 | 0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8109 | 0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8110 | 0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8111 | 0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8112 | 0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8113 | 0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8114 | 0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8115 | 0x2170, 0x217f, 484, /* ⅰ-ⅿ Ⅰ-Ⅿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8116 | 0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8117 | 0xff41, 0xff5a, 468, /* a-z A-Z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8118 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8119 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8120 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8121 | * lower case singlets |
Marko Mikulicic |
0:c0ecb8bf28eb | 8122 | * 2nd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8123 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8124 | static Rune __toupper1[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8125 | 0x00ff, 621, /* ÿ Ÿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8126 | 0x0101, 499, /* ā Ā */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8127 | 0x0103, 499, /* ă Ă */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8128 | 0x0105, 499, /* ą Ą */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8129 | 0x0107, 499, /* ć Ć */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8130 | 0x0109, 499, /* ĉ Ĉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8131 | 0x010b, 499, /* ċ Ċ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8132 | 0x010d, 499, /* č Č */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8133 | 0x010f, 499, /* ď Ď */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8134 | 0x0111, 499, /* đ Đ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8135 | 0x0113, 499, /* ē Ē */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8136 | 0x0115, 499, /* ĕ Ĕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8137 | 0x0117, 499, /* ė Ė */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8138 | 0x0119, 499, /* ę Ę */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8139 | 0x011b, 499, /* ě Ě */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8140 | 0x011d, 499, /* ĝ Ĝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8141 | 0x011f, 499, /* ğ Ğ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8142 | 0x0121, 499, /* ġ Ġ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8143 | 0x0123, 499, /* ģ Ģ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8144 | 0x0125, 499, /* ĥ Ĥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8145 | 0x0127, 499, /* ħ Ħ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8146 | 0x0129, 499, /* ĩ Ĩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8147 | 0x012b, 499, /* ī Ī */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8148 | 0x012d, 499, /* ĭ Ĭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8149 | 0x012f, 499, /* į Į */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8150 | 0x0131, 268, /* ı I */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8151 | 0x0133, 499, /* ij IJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8152 | 0x0135, 499, /* ĵ Ĵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8153 | 0x0137, 499, /* ķ Ķ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8154 | 0x013a, 499, /* ĺ Ĺ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8155 | 0x013c, 499, /* ļ Ļ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8156 | 0x013e, 499, /* ľ Ľ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8157 | 0x0140, 499, /* ŀ Ŀ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8158 | 0x0142, 499, /* ł Ł */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8159 | 0x0144, 499, /* ń Ń */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8160 | 0x0146, 499, /* ņ Ņ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8161 | 0x0148, 499, /* ň Ň */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8162 | 0x014b, 499, /* ŋ Ŋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8163 | 0x014d, 499, /* ō Ō */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8164 | 0x014f, 499, /* ŏ Ŏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8165 | 0x0151, 499, /* ő Ő */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8166 | 0x0153, 499, /* œ Œ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8167 | 0x0155, 499, /* ŕ Ŕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8168 | 0x0157, 499, /* ŗ Ŗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8169 | 0x0159, 499, /* ř Ř */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8170 | 0x015b, 499, /* ś Ś */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8171 | 0x015d, 499, /* ŝ Ŝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8172 | 0x015f, 499, /* ş Ş */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8173 | 0x0161, 499, /* š Š */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8174 | 0x0163, 499, /* ţ Ţ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8175 | 0x0165, 499, /* ť Ť */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8176 | 0x0167, 499, /* ŧ Ŧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8177 | 0x0169, 499, /* ũ Ũ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8178 | 0x016b, 499, /* ū Ū */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8179 | 0x016d, 499, /* ŭ Ŭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8180 | 0x016f, 499, /* ů Ů */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8181 | 0x0171, 499, /* ű Ű */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8182 | 0x0173, 499, /* ų Ų */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8183 | 0x0175, 499, /* ŵ Ŵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8184 | 0x0177, 499, /* ŷ Ŷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8185 | 0x017a, 499, /* ź Ź */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8186 | 0x017c, 499, /* ż Ż */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8187 | 0x017e, 499, /* ž Ž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8188 | 0x017f, 200, /* ſ S */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8189 | 0x0183, 499, /* ƃ Ƃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8190 | 0x0185, 499, /* ƅ Ƅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8191 | 0x0188, 499, /* ƈ Ƈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8192 | 0x018c, 499, /* ƌ Ƌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8193 | 0x0192, 499, /* ƒ Ƒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8194 | 0x0199, 499, /* ƙ Ƙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8195 | 0x01a1, 499, /* ơ Ơ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8196 | 0x01a3, 499, /* ƣ Ƣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8197 | 0x01a5, 499, /* ƥ Ƥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8198 | 0x01a8, 499, /* ƨ Ƨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8199 | 0x01ad, 499, /* ƭ Ƭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8200 | 0x01b0, 499, /* ư Ư */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8201 | 0x01b4, 499, /* ƴ Ƴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8202 | 0x01b6, 499, /* ƶ Ƶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8203 | 0x01b9, 499, /* ƹ Ƹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8204 | 0x01bd, 499, /* ƽ Ƽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8205 | 0x01c5, 499, /* Dž DŽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8206 | 0x01c6, 498, /* dž DŽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8207 | 0x01c8, 499, /* Lj LJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8208 | 0x01c9, 498, /* lj LJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8209 | 0x01cb, 499, /* Nj NJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8210 | 0x01cc, 498, /* nj NJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8211 | 0x01ce, 499, /* ǎ Ǎ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8212 | 0x01d0, 499, /* ǐ Ǐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8213 | 0x01d2, 499, /* ǒ Ǒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8214 | 0x01d4, 499, /* ǔ Ǔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8215 | 0x01d6, 499, /* ǖ Ǖ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8216 | 0x01d8, 499, /* ǘ Ǘ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8217 | 0x01da, 499, /* ǚ Ǚ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8218 | 0x01dc, 499, /* ǜ Ǜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8219 | 0x01df, 499, /* ǟ Ǟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8220 | 0x01e1, 499, /* ǡ Ǡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8221 | 0x01e3, 499, /* ǣ Ǣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8222 | 0x01e5, 499, /* ǥ Ǥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8223 | 0x01e7, 499, /* ǧ Ǧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8224 | 0x01e9, 499, /* ǩ Ǩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8225 | 0x01eb, 499, /* ǫ Ǫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8226 | 0x01ed, 499, /* ǭ Ǭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8227 | 0x01ef, 499, /* ǯ Ǯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8228 | 0x01f2, 499, /* Dz DZ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8229 | 0x01f3, 498, /* dz DZ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8230 | 0x01f5, 499, /* ǵ Ǵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8231 | 0x01fb, 499, /* ǻ Ǻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8232 | 0x01fd, 499, /* ǽ Ǽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8233 | 0x01ff, 499, /* ǿ Ǿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8234 | 0x0201, 499, /* ȁ Ȁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8235 | 0x0203, 499, /* ȃ Ȃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8236 | 0x0205, 499, /* ȅ Ȅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8237 | 0x0207, 499, /* ȇ Ȇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8238 | 0x0209, 499, /* ȉ Ȉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8239 | 0x020b, 499, /* ȋ Ȋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8240 | 0x020d, 499, /* ȍ Ȍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8241 | 0x020f, 499, /* ȏ Ȏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8242 | 0x0211, 499, /* ȑ Ȑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8243 | 0x0213, 499, /* ȓ Ȓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8244 | 0x0215, 499, /* ȕ Ȕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8245 | 0x0217, 499, /* ȗ Ȗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8246 | 0x0253, 290, /* ɓ Ɓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8247 | 0x0254, 294, /* ɔ Ɔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8248 | 0x025b, 297, /* ɛ Ɛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8249 | 0x0260, 295, /* ɠ Ɠ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8250 | 0x0263, 293, /* ɣ Ɣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8251 | 0x0268, 291, /* ɨ Ɨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8252 | 0x0269, 289, /* ɩ Ɩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8253 | 0x026f, 289, /* ɯ Ɯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8254 | 0x0272, 287, /* ɲ Ɲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8255 | 0x0283, 282, /* ʃ Ʃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8256 | 0x0288, 282, /* ʈ Ʈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8257 | 0x0292, 281, /* ʒ Ʒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8258 | 0x03ac, 462, /* ά Ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8259 | 0x03cc, 436, /* ό Ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8260 | 0x03d0, 438, /* ϐ Β */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8261 | 0x03d1, 443, /* ϑ Θ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8262 | 0x03d5, 453, /* ϕ Φ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8263 | 0x03d6, 446, /* ϖ Π */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8264 | 0x03e3, 499, /* ϣ Ϣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8265 | 0x03e5, 499, /* ϥ Ϥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8266 | 0x03e7, 499, /* ϧ Ϧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8267 | 0x03e9, 499, /* ϩ Ϩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8268 | 0x03eb, 499, /* ϫ Ϫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8269 | 0x03ed, 499, /* ϭ Ϭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8270 | 0x03ef, 499, /* ϯ Ϯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8271 | 0x03f0, 414, /* ϰ Κ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8272 | 0x03f1, 420, /* ϱ Ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8273 | 0x0461, 499, /* ѡ Ѡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8274 | 0x0463, 499, /* ѣ Ѣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8275 | 0x0465, 499, /* ѥ Ѥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8276 | 0x0467, 499, /* ѧ Ѧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8277 | 0x0469, 499, /* ѩ Ѩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8278 | 0x046b, 499, /* ѫ Ѫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8279 | 0x046d, 499, /* ѭ Ѭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8280 | 0x046f, 499, /* ѯ Ѯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8281 | 0x0471, 499, /* ѱ Ѱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8282 | 0x0473, 499, /* ѳ Ѳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8283 | 0x0475, 499, /* ѵ Ѵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8284 | 0x0477, 499, /* ѷ Ѷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8285 | 0x0479, 499, /* ѹ Ѹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8286 | 0x047b, 499, /* ѻ Ѻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8287 | 0x047d, 499, /* ѽ Ѽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8288 | 0x047f, 499, /* ѿ Ѿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8289 | 0x0481, 499, /* ҁ Ҁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8290 | 0x0491, 499, /* ґ Ґ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8291 | 0x0493, 499, /* ғ Ғ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8292 | 0x0495, 499, /* ҕ Ҕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8293 | 0x0497, 499, /* җ Җ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8294 | 0x0499, 499, /* ҙ Ҙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8295 | 0x049b, 499, /* қ Қ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8296 | 0x049d, 499, /* ҝ Ҝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8297 | 0x049f, 499, /* ҟ Ҟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8298 | 0x04a1, 499, /* ҡ Ҡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8299 | 0x04a3, 499, /* ң Ң */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8300 | 0x04a5, 499, /* ҥ Ҥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8301 | 0x04a7, 499, /* ҧ Ҧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8302 | 0x04a9, 499, /* ҩ Ҩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8303 | 0x04ab, 499, /* ҫ Ҫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8304 | 0x04ad, 499, /* ҭ Ҭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8305 | 0x04af, 499, /* ү Ү */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8306 | 0x04b1, 499, /* ұ Ұ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8307 | 0x04b3, 499, /* ҳ Ҳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8308 | 0x04b5, 499, /* ҵ Ҵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8309 | 0x04b7, 499, /* ҷ Ҷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8310 | 0x04b9, 499, /* ҹ Ҹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8311 | 0x04bb, 499, /* һ Һ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8312 | 0x04bd, 499, /* ҽ Ҽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8313 | 0x04bf, 499, /* ҿ Ҿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8314 | 0x04c2, 499, /* ӂ Ӂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8315 | 0x04c4, 499, /* ӄ Ӄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8316 | 0x04c8, 499, /* ӈ Ӈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8317 | 0x04cc, 499, /* ӌ Ӌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8318 | 0x04d1, 499, /* ӑ Ӑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8319 | 0x04d3, 499, /* ӓ Ӓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8320 | 0x04d5, 499, /* ӕ Ӕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8321 | 0x04d7, 499, /* ӗ Ӗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8322 | 0x04d9, 499, /* ә Ә */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8323 | 0x04db, 499, /* ӛ Ӛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8324 | 0x04dd, 499, /* ӝ Ӝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8325 | 0x04df, 499, /* ӟ Ӟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8326 | 0x04e1, 499, /* ӡ Ӡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8327 | 0x04e3, 499, /* ӣ Ӣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8328 | 0x04e5, 499, /* ӥ Ӥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8329 | 0x04e7, 499, /* ӧ Ӧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8330 | 0x04e9, 499, /* ө Ө */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8331 | 0x04eb, 499, /* ӫ Ӫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8332 | 0x04ef, 499, /* ӯ Ӯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8333 | 0x04f1, 499, /* ӱ Ӱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8334 | 0x04f3, 499, /* ӳ Ӳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8335 | 0x04f5, 499, /* ӵ Ӵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8336 | 0x04f9, 499, /* ӹ Ӹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8337 | 0x1e01, 499, /* ḁ Ḁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8338 | 0x1e03, 499, /* ḃ Ḃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8339 | 0x1e05, 499, /* ḅ Ḅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8340 | 0x1e07, 499, /* ḇ Ḇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8341 | 0x1e09, 499, /* ḉ Ḉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8342 | 0x1e0b, 499, /* ḋ Ḋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8343 | 0x1e0d, 499, /* ḍ Ḍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8344 | 0x1e0f, 499, /* ḏ Ḏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8345 | 0x1e11, 499, /* ḑ Ḑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8346 | 0x1e13, 499, /* ḓ Ḓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8347 | 0x1e15, 499, /* ḕ Ḕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8348 | 0x1e17, 499, /* ḗ Ḗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8349 | 0x1e19, 499, /* ḙ Ḙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8350 | 0x1e1b, 499, /* ḛ Ḛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8351 | 0x1e1d, 499, /* ḝ Ḝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8352 | 0x1e1f, 499, /* ḟ Ḟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8353 | 0x1e21, 499, /* ḡ Ḡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8354 | 0x1e23, 499, /* ḣ Ḣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8355 | 0x1e25, 499, /* ḥ Ḥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8356 | 0x1e27, 499, /* ḧ Ḧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8357 | 0x1e29, 499, /* ḩ Ḩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8358 | 0x1e2b, 499, /* ḫ Ḫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8359 | 0x1e2d, 499, /* ḭ Ḭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8360 | 0x1e2f, 499, /* ḯ Ḯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8361 | 0x1e31, 499, /* ḱ Ḱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8362 | 0x1e33, 499, /* ḳ Ḳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8363 | 0x1e35, 499, /* ḵ Ḵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8364 | 0x1e37, 499, /* ḷ Ḷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8365 | 0x1e39, 499, /* ḹ Ḹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8366 | 0x1e3b, 499, /* ḻ Ḻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8367 | 0x1e3d, 499, /* ḽ Ḽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8368 | 0x1e3f, 499, /* ḿ Ḿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8369 | 0x1e41, 499, /* ṁ Ṁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8370 | 0x1e43, 499, /* ṃ Ṃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8371 | 0x1e45, 499, /* ṅ Ṅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8372 | 0x1e47, 499, /* ṇ Ṇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8373 | 0x1e49, 499, /* ṉ Ṉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8374 | 0x1e4b, 499, /* ṋ Ṋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8375 | 0x1e4d, 499, /* ṍ Ṍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8376 | 0x1e4f, 499, /* ṏ Ṏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8377 | 0x1e51, 499, /* ṑ Ṑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8378 | 0x1e53, 499, /* ṓ Ṓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8379 | 0x1e55, 499, /* ṕ Ṕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8380 | 0x1e57, 499, /* ṗ Ṗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8381 | 0x1e59, 499, /* ṙ Ṙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8382 | 0x1e5b, 499, /* ṛ Ṛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8383 | 0x1e5d, 499, /* ṝ Ṝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8384 | 0x1e5f, 499, /* ṟ Ṟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8385 | 0x1e61, 499, /* ṡ Ṡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8386 | 0x1e63, 499, /* ṣ Ṣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8387 | 0x1e65, 499, /* ṥ Ṥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8388 | 0x1e67, 499, /* ṧ Ṧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8389 | 0x1e69, 499, /* ṩ Ṩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8390 | 0x1e6b, 499, /* ṫ Ṫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8391 | 0x1e6d, 499, /* ṭ Ṭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8392 | 0x1e6f, 499, /* ṯ Ṯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8393 | 0x1e71, 499, /* ṱ Ṱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8394 | 0x1e73, 499, /* ṳ Ṳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8395 | 0x1e75, 499, /* ṵ Ṵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8396 | 0x1e77, 499, /* ṷ Ṷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8397 | 0x1e79, 499, /* ṹ Ṹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8398 | 0x1e7b, 499, /* ṻ Ṻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8399 | 0x1e7d, 499, /* ṽ Ṽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8400 | 0x1e7f, 499, /* ṿ Ṿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8401 | 0x1e81, 499, /* ẁ Ẁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8402 | 0x1e83, 499, /* ẃ Ẃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8403 | 0x1e85, 499, /* ẅ Ẅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8404 | 0x1e87, 499, /* ẇ Ẇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8405 | 0x1e89, 499, /* ẉ Ẉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8406 | 0x1e8b, 499, /* ẋ Ẋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8407 | 0x1e8d, 499, /* ẍ Ẍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8408 | 0x1e8f, 499, /* ẏ Ẏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8409 | 0x1e91, 499, /* ẑ Ẑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8410 | 0x1e93, 499, /* ẓ Ẓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8411 | 0x1e95, 499, /* ẕ Ẕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8412 | 0x1ea1, 499, /* ạ Ạ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8413 | 0x1ea3, 499, /* ả Ả */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8414 | 0x1ea5, 499, /* ấ Ấ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8415 | 0x1ea7, 499, /* ầ Ầ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8416 | 0x1ea9, 499, /* ẩ Ẩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8417 | 0x1eab, 499, /* ẫ Ẫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8418 | 0x1ead, 499, /* ậ Ậ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8419 | 0x1eaf, 499, /* ắ Ắ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8420 | 0x1eb1, 499, /* ằ Ằ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8421 | 0x1eb3, 499, /* ẳ Ẳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8422 | 0x1eb5, 499, /* ẵ Ẵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8423 | 0x1eb7, 499, /* ặ Ặ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8424 | 0x1eb9, 499, /* ẹ Ẹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8425 | 0x1ebb, 499, /* ẻ Ẻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8426 | 0x1ebd, 499, /* ẽ Ẽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8427 | 0x1ebf, 499, /* ế Ế */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8428 | 0x1ec1, 499, /* ề Ề */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8429 | 0x1ec3, 499, /* ể Ể */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8430 | 0x1ec5, 499, /* ễ Ễ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8431 | 0x1ec7, 499, /* ệ Ệ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8432 | 0x1ec9, 499, /* ỉ Ỉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8433 | 0x1ecb, 499, /* ị Ị */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8434 | 0x1ecd, 499, /* ọ Ọ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8435 | 0x1ecf, 499, /* ỏ Ỏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8436 | 0x1ed1, 499, /* ố Ố */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8437 | 0x1ed3, 499, /* ồ Ồ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8438 | 0x1ed5, 499, /* ổ Ổ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8439 | 0x1ed7, 499, /* ỗ Ỗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8440 | 0x1ed9, 499, /* ộ Ộ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8441 | 0x1edb, 499, /* ớ Ớ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8442 | 0x1edd, 499, /* ờ Ờ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8443 | 0x1edf, 499, /* ở Ở */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8444 | 0x1ee1, 499, /* ỡ Ỡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8445 | 0x1ee3, 499, /* ợ Ợ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8446 | 0x1ee5, 499, /* ụ Ụ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8447 | 0x1ee7, 499, /* ủ Ủ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8448 | 0x1ee9, 499, /* ứ Ứ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8449 | 0x1eeb, 499, /* ừ Ừ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8450 | 0x1eed, 499, /* ử Ử */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8451 | 0x1eef, 499, /* ữ Ữ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8452 | 0x1ef1, 499, /* ự Ự */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8453 | 0x1ef3, 499, /* ỳ Ỳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8454 | 0x1ef5, 499, /* ỵ Ỵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8455 | 0x1ef7, 499, /* ỷ Ỷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8456 | 0x1ef9, 499, /* ỹ Ỹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8457 | 0x1f51, 508, /* ὑ Ὑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8458 | 0x1f53, 508, /* ὓ Ὓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8459 | 0x1f55, 508, /* ὕ Ὕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8460 | 0x1f57, 508, /* ὗ Ὗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8461 | 0x1fb3, 509, /* ᾳ ᾼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8462 | 0x1fc3, 509, /* ῃ ῌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8463 | 0x1fe5, 507, /* ῥ Ῥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8464 | 0x1ff3, 509, /* ῳ ῼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8465 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8467 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8468 | * upper case ranges |
Marko Mikulicic |
0:c0ecb8bf28eb | 8469 | * 3rd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8470 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8471 | static Rune __tolower2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8472 | 0x0041, 0x005a, 532, /* A-Z a-z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8473 | 0x00c0, 0x00d6, 532, /* À-Ö à-ö */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8474 | 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8475 | 0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8476 | 0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8477 | 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8478 | 0x0388, 0x038a, 537, /* Έ-Ί έ-ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8479 | 0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8480 | 0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8481 | 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8482 | 0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8483 | 0x040e, 0x040f, 580, /* Ў-Џ ў-џ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8484 | 0x0410, 0x042f, 532, /* А-Я а-я */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8485 | 0x0531, 0x0556, 548, /* Ա-Ֆ ա-ֆ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8486 | 0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8487 | 0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8488 | 0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8489 | 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8490 | 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8491 | 0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8492 | 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8493 | 0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8494 | 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8495 | 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8496 | 0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8497 | 0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8498 | 0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8499 | 0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8500 | 0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8501 | 0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8502 | 0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8503 | 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8504 | 0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8505 | 0x2160, 0x216f, 516, /* Ⅰ-Ⅿ ⅰ-ⅿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8506 | 0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8507 | 0xff21, 0xff3a, 532, /* A-Z a-z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8508 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8510 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8511 | * upper case singlets |
Marko Mikulicic |
0:c0ecb8bf28eb | 8512 | * 2nd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8513 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8514 | static Rune __tolower1[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8515 | 0x0100, 501, /* Ā ā */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8516 | 0x0102, 501, /* Ă ă */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8517 | 0x0104, 501, /* Ą ą */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8518 | 0x0106, 501, /* Ć ć */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8519 | 0x0108, 501, /* Ĉ ĉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8520 | 0x010a, 501, /* Ċ ċ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8521 | 0x010c, 501, /* Č č */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8522 | 0x010e, 501, /* Ď ď */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8523 | 0x0110, 501, /* Đ đ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8524 | 0x0112, 501, /* Ē ē */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8525 | 0x0114, 501, /* Ĕ ĕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8526 | 0x0116, 501, /* Ė ė */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8527 | 0x0118, 501, /* Ę ę */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8528 | 0x011a, 501, /* Ě ě */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8529 | 0x011c, 501, /* Ĝ ĝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8530 | 0x011e, 501, /* Ğ ğ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8531 | 0x0120, 501, /* Ġ ġ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8532 | 0x0122, 501, /* Ģ ģ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8533 | 0x0124, 501, /* Ĥ ĥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8534 | 0x0126, 501, /* Ħ ħ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8535 | 0x0128, 501, /* Ĩ ĩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8536 | 0x012a, 501, /* Ī ī */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8537 | 0x012c, 501, /* Ĭ ĭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8538 | 0x012e, 501, /* Į į */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8539 | 0x0130, 301, /* İ i */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8540 | 0x0132, 501, /* IJ ij */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8541 | 0x0134, 501, /* Ĵ ĵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8542 | 0x0136, 501, /* Ķ ķ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8543 | 0x0139, 501, /* Ĺ ĺ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8544 | 0x013b, 501, /* Ļ ļ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8545 | 0x013d, 501, /* Ľ ľ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8546 | 0x013f, 501, /* Ŀ ŀ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8547 | 0x0141, 501, /* Ł ł */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8548 | 0x0143, 501, /* Ń ń */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8549 | 0x0145, 501, /* Ņ ņ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8550 | 0x0147, 501, /* Ň ň */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8551 | 0x014a, 501, /* Ŋ ŋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8552 | 0x014c, 501, /* Ō ō */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8553 | 0x014e, 501, /* Ŏ ŏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8554 | 0x0150, 501, /* Ő ő */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8555 | 0x0152, 501, /* Œ œ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8556 | 0x0154, 501, /* Ŕ ŕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8557 | 0x0156, 501, /* Ŗ ŗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8558 | 0x0158, 501, /* Ř ř */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8559 | 0x015a, 501, /* Ś ś */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8560 | 0x015c, 501, /* Ŝ ŝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8561 | 0x015e, 501, /* Ş ş */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8562 | 0x0160, 501, /* Š š */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8563 | 0x0162, 501, /* Ţ ţ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8564 | 0x0164, 501, /* Ť ť */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8565 | 0x0166, 501, /* Ŧ ŧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8566 | 0x0168, 501, /* Ũ ũ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8567 | 0x016a, 501, /* Ū ū */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8568 | 0x016c, 501, /* Ŭ ŭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8569 | 0x016e, 501, /* Ů ů */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8570 | 0x0170, 501, /* Ű ű */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8571 | 0x0172, 501, /* Ų ų */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8572 | 0x0174, 501, /* Ŵ ŵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8573 | 0x0176, 501, /* Ŷ ŷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8574 | 0x0178, 379, /* Ÿ ÿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8575 | 0x0179, 501, /* Ź ź */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8576 | 0x017b, 501, /* Ż ż */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8577 | 0x017d, 501, /* Ž ž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8578 | 0x0181, 710, /* Ɓ ɓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8579 | 0x0182, 501, /* Ƃ ƃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8580 | 0x0184, 501, /* Ƅ ƅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8581 | 0x0186, 706, /* Ɔ ɔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8582 | 0x0187, 501, /* Ƈ ƈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8583 | 0x018b, 501, /* Ƌ ƌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8584 | 0x0190, 703, /* Ɛ ɛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8585 | 0x0191, 501, /* Ƒ ƒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8586 | 0x0193, 705, /* Ɠ ɠ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8587 | 0x0194, 707, /* Ɣ ɣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8588 | 0x0196, 711, /* Ɩ ɩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8589 | 0x0197, 709, /* Ɨ ɨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8590 | 0x0198, 501, /* Ƙ ƙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8591 | 0x019c, 711, /* Ɯ ɯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8592 | 0x019d, 713, /* Ɲ ɲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8593 | 0x01a0, 501, /* Ơ ơ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8594 | 0x01a2, 501, /* Ƣ ƣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8595 | 0x01a4, 501, /* Ƥ ƥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8596 | 0x01a7, 501, /* Ƨ ƨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8597 | 0x01a9, 718, /* Ʃ ʃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8598 | 0x01ac, 501, /* Ƭ ƭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8599 | 0x01ae, 718, /* Ʈ ʈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8600 | 0x01af, 501, /* Ư ư */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8601 | 0x01b3, 501, /* Ƴ ƴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8602 | 0x01b5, 501, /* Ƶ ƶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8603 | 0x01b7, 719, /* Ʒ ʒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8604 | 0x01b8, 501, /* Ƹ ƹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8605 | 0x01bc, 501, /* Ƽ ƽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8606 | 0x01c4, 502, /* DŽ dž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8607 | 0x01c5, 501, /* Dž dž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8608 | 0x01c7, 502, /* LJ lj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8609 | 0x01c8, 501, /* Lj lj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8610 | 0x01ca, 502, /* NJ nj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8611 | 0x01cb, 501, /* Nj nj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8612 | 0x01cd, 501, /* Ǎ ǎ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8613 | 0x01cf, 501, /* Ǐ ǐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8614 | 0x01d1, 501, /* Ǒ ǒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8615 | 0x01d3, 501, /* Ǔ ǔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8616 | 0x01d5, 501, /* Ǖ ǖ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8617 | 0x01d7, 501, /* Ǘ ǘ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8618 | 0x01d9, 501, /* Ǚ ǚ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8619 | 0x01db, 501, /* Ǜ ǜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8620 | 0x01de, 501, /* Ǟ ǟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8621 | 0x01e0, 501, /* Ǡ ǡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8622 | 0x01e2, 501, /* Ǣ ǣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8623 | 0x01e4, 501, /* Ǥ ǥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8624 | 0x01e6, 501, /* Ǧ ǧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8625 | 0x01e8, 501, /* Ǩ ǩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8626 | 0x01ea, 501, /* Ǫ ǫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8627 | 0x01ec, 501, /* Ǭ ǭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8628 | 0x01ee, 501, /* Ǯ ǯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8629 | 0x01f1, 502, /* DZ dz */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8630 | 0x01f2, 501, /* Dz dz */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8631 | 0x01f4, 501, /* Ǵ ǵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8632 | 0x01fa, 501, /* Ǻ ǻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8633 | 0x01fc, 501, /* Ǽ ǽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8634 | 0x01fe, 501, /* Ǿ ǿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8635 | 0x0200, 501, /* Ȁ ȁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8636 | 0x0202, 501, /* Ȃ ȃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8637 | 0x0204, 501, /* Ȅ ȅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8638 | 0x0206, 501, /* Ȇ ȇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8639 | 0x0208, 501, /* Ȉ ȉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8640 | 0x020a, 501, /* Ȋ ȋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8641 | 0x020c, 501, /* Ȍ ȍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8642 | 0x020e, 501, /* Ȏ ȏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8643 | 0x0210, 501, /* Ȑ ȑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8644 | 0x0212, 501, /* Ȓ ȓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8645 | 0x0214, 501, /* Ȕ ȕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8646 | 0x0216, 501, /* Ȗ ȗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8647 | 0x0386, 538, /* Ά ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8648 | 0x038c, 564, /* Ό ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8649 | 0x03e2, 501, /* Ϣ ϣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8650 | 0x03e4, 501, /* Ϥ ϥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8651 | 0x03e6, 501, /* Ϧ ϧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8652 | 0x03e8, 501, /* Ϩ ϩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8653 | 0x03ea, 501, /* Ϫ ϫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8654 | 0x03ec, 501, /* Ϭ ϭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8655 | 0x03ee, 501, /* Ϯ ϯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8656 | 0x0460, 501, /* Ѡ ѡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8657 | 0x0462, 501, /* Ѣ ѣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8658 | 0x0464, 501, /* Ѥ ѥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8659 | 0x0466, 501, /* Ѧ ѧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8660 | 0x0468, 501, /* Ѩ ѩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8661 | 0x046a, 501, /* Ѫ ѫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8662 | 0x046c, 501, /* Ѭ ѭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8663 | 0x046e, 501, /* Ѯ ѯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8664 | 0x0470, 501, /* Ѱ ѱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8665 | 0x0472, 501, /* Ѳ ѳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8666 | 0x0474, 501, /* Ѵ ѵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8667 | 0x0476, 501, /* Ѷ ѷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8668 | 0x0478, 501, /* Ѹ ѹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8669 | 0x047a, 501, /* Ѻ ѻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8670 | 0x047c, 501, /* Ѽ ѽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8671 | 0x047e, 501, /* Ѿ ѿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8672 | 0x0480, 501, /* Ҁ ҁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8673 | 0x0490, 501, /* Ґ ґ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8674 | 0x0492, 501, /* Ғ ғ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8675 | 0x0494, 501, /* Ҕ ҕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8676 | 0x0496, 501, /* Җ җ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8677 | 0x0498, 501, /* Ҙ ҙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8678 | 0x049a, 501, /* Қ қ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8679 | 0x049c, 501, /* Ҝ ҝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8680 | 0x049e, 501, /* Ҟ ҟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8681 | 0x04a0, 501, /* Ҡ ҡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8682 | 0x04a2, 501, /* Ң ң */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8683 | 0x04a4, 501, /* Ҥ ҥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8684 | 0x04a6, 501, /* Ҧ ҧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8685 | 0x04a8, 501, /* Ҩ ҩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8686 | 0x04aa, 501, /* Ҫ ҫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8687 | 0x04ac, 501, /* Ҭ ҭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8688 | 0x04ae, 501, /* Ү ү */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8689 | 0x04b0, 501, /* Ұ ұ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8690 | 0x04b2, 501, /* Ҳ ҳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8691 | 0x04b4, 501, /* Ҵ ҵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8692 | 0x04b6, 501, /* Ҷ ҷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8693 | 0x04b8, 501, /* Ҹ ҹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8694 | 0x04ba, 501, /* Һ һ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8695 | 0x04bc, 501, /* Ҽ ҽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8696 | 0x04be, 501, /* Ҿ ҿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8697 | 0x04c1, 501, /* Ӂ ӂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8698 | 0x04c3, 501, /* Ӄ ӄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8699 | 0x04c7, 501, /* Ӈ ӈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8700 | 0x04cb, 501, /* Ӌ ӌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8701 | 0x04d0, 501, /* Ӑ ӑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8702 | 0x04d2, 501, /* Ӓ ӓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8703 | 0x04d4, 501, /* Ӕ ӕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8704 | 0x04d6, 501, /* Ӗ ӗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8705 | 0x04d8, 501, /* Ә ә */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8706 | 0x04da, 501, /* Ӛ ӛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8707 | 0x04dc, 501, /* Ӝ ӝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8708 | 0x04de, 501, /* Ӟ ӟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8709 | 0x04e0, 501, /* Ӡ ӡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8710 | 0x04e2, 501, /* Ӣ ӣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8711 | 0x04e4, 501, /* Ӥ ӥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8712 | 0x04e6, 501, /* Ӧ ӧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8713 | 0x04e8, 501, /* Ө ө */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8714 | 0x04ea, 501, /* Ӫ ӫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8715 | 0x04ee, 501, /* Ӯ ӯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8716 | 0x04f0, 501, /* Ӱ ӱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8717 | 0x04f2, 501, /* Ӳ ӳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8718 | 0x04f4, 501, /* Ӵ ӵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8719 | 0x04f8, 501, /* Ӹ ӹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8720 | 0x1e00, 501, /* Ḁ ḁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8721 | 0x1e02, 501, /* Ḃ ḃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8722 | 0x1e04, 501, /* Ḅ ḅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8723 | 0x1e06, 501, /* Ḇ ḇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8724 | 0x1e08, 501, /* Ḉ ḉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8725 | 0x1e0a, 501, /* Ḋ ḋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8726 | 0x1e0c, 501, /* Ḍ ḍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8727 | 0x1e0e, 501, /* Ḏ ḏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8728 | 0x1e10, 501, /* Ḑ ḑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8729 | 0x1e12, 501, /* Ḓ ḓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8730 | 0x1e14, 501, /* Ḕ ḕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8731 | 0x1e16, 501, /* Ḗ ḗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8732 | 0x1e18, 501, /* Ḙ ḙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8733 | 0x1e1a, 501, /* Ḛ ḛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8734 | 0x1e1c, 501, /* Ḝ ḝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8735 | 0x1e1e, 501, /* Ḟ ḟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8736 | 0x1e20, 501, /* Ḡ ḡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8737 | 0x1e22, 501, /* Ḣ ḣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8738 | 0x1e24, 501, /* Ḥ ḥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8739 | 0x1e26, 501, /* Ḧ ḧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8740 | 0x1e28, 501, /* Ḩ ḩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8741 | 0x1e2a, 501, /* Ḫ ḫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8742 | 0x1e2c, 501, /* Ḭ ḭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8743 | 0x1e2e, 501, /* Ḯ ḯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8744 | 0x1e30, 501, /* Ḱ ḱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8745 | 0x1e32, 501, /* Ḳ ḳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8746 | 0x1e34, 501, /* Ḵ ḵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8747 | 0x1e36, 501, /* Ḷ ḷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8748 | 0x1e38, 501, /* Ḹ ḹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8749 | 0x1e3a, 501, /* Ḻ ḻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8750 | 0x1e3c, 501, /* Ḽ ḽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8751 | 0x1e3e, 501, /* Ḿ ḿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8752 | 0x1e40, 501, /* Ṁ ṁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8753 | 0x1e42, 501, /* Ṃ ṃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8754 | 0x1e44, 501, /* Ṅ ṅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8755 | 0x1e46, 501, /* Ṇ ṇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8756 | 0x1e48, 501, /* Ṉ ṉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8757 | 0x1e4a, 501, /* Ṋ ṋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8758 | 0x1e4c, 501, /* Ṍ ṍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8759 | 0x1e4e, 501, /* Ṏ ṏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8760 | 0x1e50, 501, /* Ṑ ṑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8761 | 0x1e52, 501, /* Ṓ ṓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8762 | 0x1e54, 501, /* Ṕ ṕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8763 | 0x1e56, 501, /* Ṗ ṗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8764 | 0x1e58, 501, /* Ṙ ṙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8765 | 0x1e5a, 501, /* Ṛ ṛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8766 | 0x1e5c, 501, /* Ṝ ṝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8767 | 0x1e5e, 501, /* Ṟ ṟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8768 | 0x1e60, 501, /* Ṡ ṡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8769 | 0x1e62, 501, /* Ṣ ṣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8770 | 0x1e64, 501, /* Ṥ ṥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8771 | 0x1e66, 501, /* Ṧ ṧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8772 | 0x1e68, 501, /* Ṩ ṩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8773 | 0x1e6a, 501, /* Ṫ ṫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8774 | 0x1e6c, 501, /* Ṭ ṭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8775 | 0x1e6e, 501, /* Ṯ ṯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8776 | 0x1e70, 501, /* Ṱ ṱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8777 | 0x1e72, 501, /* Ṳ ṳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8778 | 0x1e74, 501, /* Ṵ ṵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8779 | 0x1e76, 501, /* Ṷ ṷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8780 | 0x1e78, 501, /* Ṹ ṹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8781 | 0x1e7a, 501, /* Ṻ ṻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8782 | 0x1e7c, 501, /* Ṽ ṽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8783 | 0x1e7e, 501, /* Ṿ ṿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8784 | 0x1e80, 501, /* Ẁ ẁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8785 | 0x1e82, 501, /* Ẃ ẃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8786 | 0x1e84, 501, /* Ẅ ẅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8787 | 0x1e86, 501, /* Ẇ ẇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8788 | 0x1e88, 501, /* Ẉ ẉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8789 | 0x1e8a, 501, /* Ẋ ẋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8790 | 0x1e8c, 501, /* Ẍ ẍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8791 | 0x1e8e, 501, /* Ẏ ẏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8792 | 0x1e90, 501, /* Ẑ ẑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8793 | 0x1e92, 501, /* Ẓ ẓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8794 | 0x1e94, 501, /* Ẕ ẕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8795 | 0x1ea0, 501, /* Ạ ạ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8796 | 0x1ea2, 501, /* Ả ả */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8797 | 0x1ea4, 501, /* Ấ ấ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8798 | 0x1ea6, 501, /* Ầ ầ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8799 | 0x1ea8, 501, /* Ẩ ẩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8800 | 0x1eaa, 501, /* Ẫ ẫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8801 | 0x1eac, 501, /* Ậ ậ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8802 | 0x1eae, 501, /* Ắ ắ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8803 | 0x1eb0, 501, /* Ằ ằ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8804 | 0x1eb2, 501, /* Ẳ ẳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8805 | 0x1eb4, 501, /* Ẵ ẵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8806 | 0x1eb6, 501, /* Ặ ặ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8807 | 0x1eb8, 501, /* Ẹ ẹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8808 | 0x1eba, 501, /* Ẻ ẻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8809 | 0x1ebc, 501, /* Ẽ ẽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8810 | 0x1ebe, 501, /* Ế ế */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8811 | 0x1ec0, 501, /* Ề ề */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8812 | 0x1ec2, 501, /* Ể ể */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8813 | 0x1ec4, 501, /* Ễ ễ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8814 | 0x1ec6, 501, /* Ệ ệ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8815 | 0x1ec8, 501, /* Ỉ ỉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8816 | 0x1eca, 501, /* Ị ị */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8817 | 0x1ecc, 501, /* Ọ ọ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8818 | 0x1ece, 501, /* Ỏ ỏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8819 | 0x1ed0, 501, /* Ố ố */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8820 | 0x1ed2, 501, /* Ồ ồ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8821 | 0x1ed4, 501, /* Ổ ổ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8822 | 0x1ed6, 501, /* Ỗ ỗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8823 | 0x1ed8, 501, /* Ộ ộ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8824 | 0x1eda, 501, /* Ớ ớ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8825 | 0x1edc, 501, /* Ờ ờ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8826 | 0x1ede, 501, /* Ở ở */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8827 | 0x1ee0, 501, /* Ỡ ỡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8828 | 0x1ee2, 501, /* Ợ ợ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8829 | 0x1ee4, 501, /* Ụ ụ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8830 | 0x1ee6, 501, /* Ủ ủ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8831 | 0x1ee8, 501, /* Ứ ứ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8832 | 0x1eea, 501, /* Ừ ừ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8833 | 0x1eec, 501, /* Ử ử */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8834 | 0x1eee, 501, /* Ữ ữ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8835 | 0x1ef0, 501, /* Ự ự */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8836 | 0x1ef2, 501, /* Ỳ ỳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8837 | 0x1ef4, 501, /* Ỵ ỵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8838 | 0x1ef6, 501, /* Ỷ ỷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8839 | 0x1ef8, 501, /* Ỹ ỹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8840 | 0x1f59, 492, /* Ὑ ὑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8841 | 0x1f5b, 492, /* Ὓ ὓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8842 | 0x1f5d, 492, /* Ὕ ὕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8843 | 0x1f5f, 492, /* Ὗ ὗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8844 | 0x1fbc, 491, /* ᾼ ᾳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8845 | 0x1fcc, 491, /* ῌ ῃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8846 | 0x1fec, 493, /* Ῥ ῥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8847 | 0x1ffc, 491, /* ῼ ῳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8848 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8850 | static Rune *rune_bsearch(Rune c, Rune *t, int n, int ne) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8851 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8852 | int m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8854 | while (n > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8855 | m = n / 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8856 | p = t + m * ne; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8857 | if (c >= p[0]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8858 | t = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8859 | n = n - m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8860 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 8861 | n = m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8862 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8863 | if (n && c >= t[0]) return t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8864 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8867 | Rune tolowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8868 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8869 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8870 | p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8871 | if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8872 | p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8873 | if (p && c == p[0]) return c + p[1] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8874 | return c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8875 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8876 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8877 | Rune toupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8878 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8880 | p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8881 | if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8882 | p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8883 | if (p && c == p[0]) return c + p[1] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8884 | return c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8885 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8887 | int islowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8888 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8890 | p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8891 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8892 | p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8893 | if (p && c == p[0]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8894 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8895 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8897 | int isupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8898 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8899 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8900 | p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8901 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8902 | p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8903 | if (p && c == p[0]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8904 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8907 | int isdigitrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8908 | return c >= '0' && c <= '9'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8909 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8911 | int isnewline(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8912 | return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8913 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8915 | int iswordchar(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8916 | return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') || |
Marko Mikulicic |
0:c0ecb8bf28eb | 8917 | (c >= 'A' && c <= 'Z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8918 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8920 | int isalpharune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8921 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8923 | if (isupperrune(c) || islowerrune(c)) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8924 | p = rune_bsearch(c, __alpha2, nelem(__alpha2) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8925 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8926 | p = rune_bsearch(c, __alpha1, nelem(__alpha1), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8927 | if (p && c == p[0]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8928 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8929 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8931 | int isspacerune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8932 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8934 | p = rune_bsearch(c, __space2, nelem(__space2) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8935 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8936 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8937 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8939 | #else /* CS_ENABLE_UTF8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8941 | int chartorune(Rune *rune, const char *str) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8942 | *rune = *(uchar *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8943 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8944 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8946 | int fullrune(const char *str, int n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8947 | (void) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8948 | return (n <= 0) ? 0 : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8949 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8950 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8951 | int isdigitrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8952 | return isdigit(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8953 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8955 | int isnewline(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8956 | return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8957 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8959 | int iswordchar(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8960 | return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') || |
Marko Mikulicic |
0:c0ecb8bf28eb | 8961 | (c >= 'A' && c <= 'Z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8964 | int isalpharune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8965 | return isalpha(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8966 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8967 | int islowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8968 | return islower(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8970 | int isspacerune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8971 | return isspace(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8973 | int isupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8974 | return isupper(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8975 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8976 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8977 | int runetochar(char *str, Rune *rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8978 | str[0] = (char) *rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8979 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8980 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8982 | Rune tolowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8983 | return tolower(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8984 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8985 | Rune toupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8986 | return toupper(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8987 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8988 | int utfnlen(const char *s, long m) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8989 | (void) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8990 | return (int) c_strnlen(s, (size_t) m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8991 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8993 | const char *utfnshift(const char *s, long m) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8994 | return s + m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8995 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8996 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8997 | #endif /* CS_ENABLE_UTF8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8999 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9000 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9001 | #line 1 "common/base64.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9002 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9003 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9004 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 9005 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 9006 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9008 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 9009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9010 | /* Amalgamated: #include "common/base64.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9011 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9013 | /* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9015 | #define NUM_UPPERCASES ('Z' - 'A' + 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9016 | #define NUM_LETTERS (NUM_UPPERCASES * 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9017 | #define NUM_DIGITS ('9' - '0' + 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9018 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9019 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9020 | * Emit a base64 code char. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9021 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 9022 | * Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps |
Marko Mikulicic |
0:c0ecb8bf28eb | 9023 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9024 | static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9025 | if (v < NUM_UPPERCASES) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9026 | ctx->b64_putc(v + 'A', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9027 | } else if (v < (NUM_LETTERS)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9028 | ctx->b64_putc(v - NUM_UPPERCASES + 'a', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9029 | } else if (v < (NUM_LETTERS + NUM_DIGITS)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9030 | ctx->b64_putc(v - NUM_LETTERS + '0', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9031 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9032 | ctx->b64_putc(v - NUM_LETTERS - NUM_DIGITS == 0 ? '+' : '/', |
Marko Mikulicic |
0:c0ecb8bf28eb | 9033 | ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9034 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9035 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9037 | static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9038 | int a, b, c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9040 | a = ctx->chunk[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9041 | b = ctx->chunk[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9042 | c = ctx->chunk[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9043 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9044 | cs_base64_emit_code(ctx, a >> 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9045 | cs_base64_emit_code(ctx, ((a & 3) << 4) | (b >> 4)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9046 | if (ctx->chunk_size > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9047 | cs_base64_emit_code(ctx, (b & 15) << 2 | (c >> 6)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9049 | if (ctx->chunk_size > 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9050 | cs_base64_emit_code(ctx, c & 63); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9051 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9052 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9054 | void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9055 | void *user_data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9056 | ctx->chunk_size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9057 | ctx->b64_putc = b64_putc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9058 | ctx->user_data = user_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9059 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9061 | void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9062 | const unsigned char *src = (const unsigned char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9063 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9064 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9065 | ctx->chunk[ctx->chunk_size++] = src[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9066 | if (ctx->chunk_size == 3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9067 | cs_base64_emit_chunk(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9068 | ctx->chunk_size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9069 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9070 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9071 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9073 | void cs_base64_finish(struct cs_base64_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9074 | if (ctx->chunk_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9075 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9076 | memset(&ctx->chunk[ctx->chunk_size], 0, 3 - ctx->chunk_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9077 | cs_base64_emit_chunk(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9078 | for (i = 0; i < (3 - ctx->chunk_size); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9079 | ctx->b64_putc('=', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9080 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9082 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9084 | #define BASE64_ENCODE_BODY \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9085 | static const char *b64 = \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9086 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9087 | int i, j, a, b, c; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9088 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9089 | for (i = j = 0; i < src_len; i += 3) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9090 | a = src[i]; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9091 | b = i + 1 >= src_len ? 0 : src[i + 1]; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9092 | c = i + 2 >= src_len ? 0 : src[i + 2]; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9093 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9094 | BASE64_OUT(b64[a >> 2]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9095 | BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9096 | if (i + 1 < src_len) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9097 | BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9098 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9099 | if (i + 2 < src_len) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9100 | BASE64_OUT(b64[c & 63]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9101 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9102 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9103 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9104 | while (j % 4 != 0) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9105 | BASE64_OUT('='); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9106 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9107 | BASE64_FLUSH() |
Marko Mikulicic |
0:c0ecb8bf28eb | 9108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9109 | #define BASE64_OUT(ch) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9110 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9111 | dst[j++] = (ch); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9112 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9113 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9114 | #define BASE64_FLUSH() \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9115 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9116 | dst[j++] = '\0'; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9117 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9118 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9119 | void cs_base64_encode(const unsigned char *src, int src_len, char *dst) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9120 | BASE64_ENCODE_BODY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9121 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9123 | #undef BASE64_OUT |
Marko Mikulicic |
0:c0ecb8bf28eb | 9124 | #undef BASE64_FLUSH |
Marko Mikulicic |
0:c0ecb8bf28eb | 9125 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9126 | #ifndef CS_DISABLE_STDIO |
Marko Mikulicic |
0:c0ecb8bf28eb | 9127 | #define BASE64_OUT(ch) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9128 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9129 | fprintf(f, "%c", (ch)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9130 | j++; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9131 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9132 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9133 | #define BASE64_FLUSH() |
Marko Mikulicic |
0:c0ecb8bf28eb | 9134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9135 | void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9136 | BASE64_ENCODE_BODY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9137 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9139 | #undef BASE64_OUT |
Marko Mikulicic |
0:c0ecb8bf28eb | 9140 | #undef BASE64_FLUSH |
Marko Mikulicic |
0:c0ecb8bf28eb | 9141 | #endif /* !CS_DISABLE_STDIO */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9143 | /* Convert one byte of encoded base64 input stream to 6-bit chunk */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9144 | static unsigned char from_b64(unsigned char ch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9145 | /* Inverse lookup map */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9146 | static const unsigned char tab[128] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9147 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9148 | 255, 255, 255, 255, /* 0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9149 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9150 | 255, 255, 255, 255, /* 8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9151 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9152 | 255, 255, 255, 255, /* 16 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9153 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9154 | 255, 255, 255, 255, /* 24 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9155 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9156 | 255, 255, 255, 255, /* 32 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9157 | 255, 255, 255, 62, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9158 | 255, 255, 255, 63, /* 40 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9159 | 52, 53, 54, 55, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9160 | 56, 57, 58, 59, /* 48 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9161 | 60, 61, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9162 | 255, 200, 255, 255, /* 56 '=' is 200, on index 61 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9163 | 255, 0, 1, 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9164 | 3, 4, 5, 6, /* 64 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9165 | 7, 8, 9, 10, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9166 | 11, 12, 13, 14, /* 72 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9167 | 15, 16, 17, 18, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9168 | 19, 20, 21, 22, /* 80 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9169 | 23, 24, 25, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9170 | 255, 255, 255, 255, /* 88 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9171 | 255, 26, 27, 28, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9172 | 29, 30, 31, 32, /* 96 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9173 | 33, 34, 35, 36, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9174 | 37, 38, 39, 40, /* 104 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9175 | 41, 42, 43, 44, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9176 | 45, 46, 47, 48, /* 112 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9177 | 49, 50, 51, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9178 | 255, 255, 255, 255, /* 120 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9179 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9180 | return tab[ch & 127]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9181 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9182 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9183 | int cs_base64_decode(const unsigned char *s, int len, char *dst) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9184 | unsigned char a, b, c, d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9185 | int orig_len = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9186 | while (len >= 4 && (a = from_b64(s[0])) != 255 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 9187 | (b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 9188 | (d = from_b64(s[3])) != 255) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9189 | s += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9190 | len -= 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9191 | if (a == 200 || b == 200) break; /* '=' can't be there */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9192 | *dst++ = a << 2 | b >> 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9193 | if (c == 200) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9194 | *dst++ = b << 4 | c >> 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9195 | if (d == 200) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9196 | *dst++ = c << 6 | d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9197 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9198 | *dst = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9199 | return orig_len - len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9201 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9202 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9203 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9204 | #line 1 "common/md5.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9205 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9206 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9207 | * This code implements the MD5 message-digest algorithm. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9208 | * The algorithm is due to Ron Rivest. This code was |
Marko Mikulicic |
0:c0ecb8bf28eb | 9209 | * written by Colin Plumb in 1993, no copyright is claimed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9210 | * This code is in the public domain; do with it what you wish. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9211 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 9212 | * Equivalent code is available from RSA Data Security, Inc. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9213 | * This code has been tested against that, and is equivalent, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9214 | * except that you don't need to include two pages of legalese |
Marko Mikulicic |
0:c0ecb8bf28eb | 9215 | * with every copy. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9216 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 9217 | * To compute the message digest of a chunk of bytes, declare an |
Marko Mikulicic |
0:c0ecb8bf28eb | 9218 | * MD5Context structure, pass it to MD5Init, call MD5Update as |
Marko Mikulicic |
0:c0ecb8bf28eb | 9219 | * needed on buffers full of bytes, and then call MD5Final, which |
Marko Mikulicic |
0:c0ecb8bf28eb | 9220 | * will fill a supplied 16-byte array with the digest. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9221 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9223 | #if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9224 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9225 | /* Amalgamated: #include "common/md5.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9226 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9227 | #ifndef CS_ENABLE_NATIVE_MD5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9228 | static void byteReverse(unsigned char *buf, unsigned longs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9229 | /* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9230 | #if BYTE_ORDER == BIG_ENDIAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 9231 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9232 | uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9233 | ((unsigned) buf[1] << 8 | buf[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9234 | *(uint32_t *) buf = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9235 | buf += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9236 | } while (--longs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9237 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 9238 | (void) buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9239 | (void) longs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9240 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9241 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9243 | #define F1(x, y, z) (z ^ (x & (y ^ z))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9244 | #define F2(x, y, z) F1(z, x, y) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9245 | #define F3(x, y, z) (x ^ y ^ z) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9246 | #define F4(x, y, z) (y ^ (x | ~z)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9248 | #define MD5STEP(f, w, x, y, z, data, s) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9249 | (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9251 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9252 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious |
Marko Mikulicic |
0:c0ecb8bf28eb | 9253 | * initialization constants. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9254 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9255 | void MD5_Init(MD5_CTX *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9256 | ctx->buf[0] = 0x67452301; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9257 | ctx->buf[1] = 0xefcdab89; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9258 | ctx->buf[2] = 0x98badcfe; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9259 | ctx->buf[3] = 0x10325476; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9261 | ctx->bits[0] = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9262 | ctx->bits[1] = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9263 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9264 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9265 | static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9266 | register uint32_t a, b, c, d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9268 | a = buf[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9269 | b = buf[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9270 | c = buf[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9271 | d = buf[3]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9272 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9273 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9274 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9275 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9276 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9277 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9278 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9279 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9280 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9281 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9282 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9283 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9284 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9285 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9286 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9287 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9288 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9290 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9291 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9292 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9293 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9294 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9295 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9296 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9297 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9298 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9299 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9300 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9301 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9302 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9303 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9304 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9305 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9307 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9308 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9309 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9310 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9311 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9312 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9313 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9314 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9315 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9316 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9317 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9318 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9319 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9320 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9321 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9322 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9324 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9325 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9326 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9327 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9328 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9329 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9330 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9331 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9332 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9333 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9334 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9335 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9336 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9337 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9338 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9339 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9341 | buf[0] += a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9342 | buf[1] += b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9343 | buf[2] += c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9344 | buf[3] += d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9345 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9347 | void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9348 | uint32_t t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9350 | t = ctx->bits[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9351 | if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9352 | ctx->bits[1] += (uint32_t) len >> 29; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9354 | t = (t >> 3) & 0x3f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9356 | if (t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9357 | unsigned char *p = (unsigned char *) ctx->in + t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9358 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9359 | t = 64 - t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9360 | if (len < t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9361 | memcpy(p, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9362 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9364 | memcpy(p, buf, t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9365 | byteReverse(ctx->in, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9366 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9367 | buf += t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9368 | len -= t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9371 | while (len >= 64) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9372 | memcpy(ctx->in, buf, 64); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9373 | byteReverse(ctx->in, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9374 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9375 | buf += 64; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9376 | len -= 64; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9377 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9379 | memcpy(ctx->in, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9380 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9381 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9382 | void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9383 | unsigned count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9384 | unsigned char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9385 | uint32_t *a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9387 | count = (ctx->bits[0] >> 3) & 0x3F; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9389 | p = ctx->in + count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9390 | *p++ = 0x80; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9391 | count = 64 - 1 - count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9392 | if (count < 8) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9393 | memset(p, 0, count); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9394 | byteReverse(ctx->in, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9395 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9396 | memset(ctx->in, 0, 56); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9397 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9398 | memset(p, 0, count - 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9399 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9400 | byteReverse(ctx->in, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9402 | a = (uint32_t *) ctx->in; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9403 | a[14] = ctx->bits[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9404 | a[15] = ctx->bits[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9406 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9407 | byteReverse((unsigned char *) ctx->buf, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9408 | memcpy(digest, ctx->buf, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9409 | memset((char *) ctx, 0, sizeof(*ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9410 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9411 | #endif /* CS_ENABLE_NATIVE_MD5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9413 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9414 | * Stringify binary data. Output buffer size must be 2 * size_of_input + 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9415 | * because each byte of input takes 2 bytes in string representation |
Marko Mikulicic |
0:c0ecb8bf28eb | 9416 | * plus 1 byte for the terminating \0 character. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9417 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9418 | void cs_to_hex(char *to, const unsigned char *p, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9419 | static const char *hex = "0123456789abcdef"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9421 | for (; len--; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9422 | *to++ = hex[p[0] >> 4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9423 | *to++ = hex[p[0] & 0x0f]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9424 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9425 | *to = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9428 | char *cs_md5(char buf[33], ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9429 | unsigned char hash[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9430 | const unsigned char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9431 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9432 | MD5_CTX ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9434 | MD5_Init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9436 | va_start(ap, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9437 | while ((p = va_arg(ap, const unsigned char *) ) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9438 | size_t len = va_arg(ap, size_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9439 | MD5_Update(&ctx, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9440 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9441 | va_end(ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9443 | MD5_Final(hash, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9444 | cs_to_hex(buf, hash, sizeof(hash)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9446 | return buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9447 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9449 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9450 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9451 | #line 1 "common/sha1.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9452 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9453 | /* Copyright(c) By Steve Reid <steve@edmweb.com> */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9454 | /* 100% Public Domain */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9456 | #if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9457 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9458 | /* Amalgamated: #include "common/sha1.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9460 | #define SHA1HANDSOFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 9461 | #if defined(__sun) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9462 | /* Amalgamated: #include "common/solarisfixes.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9463 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9465 | union char64long16 { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9466 | unsigned char c[64]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9467 | uint32_t l[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9468 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9470 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9472 | static uint32_t blk0(union char64long16 *block, int i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9473 | /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9474 | #if BYTE_ORDER == LITTLE_ENDIAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 9475 | block->l[i] = |
Marko Mikulicic |
0:c0ecb8bf28eb | 9476 | (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9477 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9478 | return block->l[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9479 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9481 | /* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9482 | #undef blk |
Marko Mikulicic |
0:c0ecb8bf28eb | 9483 | #undef R0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9484 | #undef R1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9485 | #undef R2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9486 | #undef R3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9487 | #undef R4 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9489 | #define blk(i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9490 | (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9491 | block->l[(i + 2) & 15] ^ block->l[i & 15], \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9492 | 1)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9493 | #define R0(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9494 | z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9495 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9496 | #define R1(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9497 | z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9498 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9499 | #define R2(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9500 | z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9501 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9502 | #define R3(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9503 | z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9504 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9505 | #define R4(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9506 | z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9507 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9509 | void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9510 | uint32_t a, b, c, d, e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9511 | union char64long16 block[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9513 | memcpy(block, buffer, 64); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9514 | a = state[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9515 | b = state[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9516 | c = state[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9517 | d = state[3]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9518 | e = state[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9519 | R0(a, b, c, d, e, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9520 | R0(e, a, b, c, d, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9521 | R0(d, e, a, b, c, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9522 | R0(c, d, e, a, b, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9523 | R0(b, c, d, e, a, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9524 | R0(a, b, c, d, e, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9525 | R0(e, a, b, c, d, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9526 | R0(d, e, a, b, c, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9527 | R0(c, d, e, a, b, 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9528 | R0(b, c, d, e, a, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9529 | R0(a, b, c, d, e, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9530 | R0(e, a, b, c, d, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9531 | R0(d, e, a, b, c, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9532 | R0(c, d, e, a, b, 13); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9533 | R0(b, c, d, e, a, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9534 | R0(a, b, c, d, e, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9535 | R1(e, a, b, c, d, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9536 | R1(d, e, a, b, c, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9537 | R1(c, d, e, a, b, 18); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9538 | R1(b, c, d, e, a, 19); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9539 | R2(a, b, c, d, e, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9540 | R2(e, a, b, c, d, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9541 | R2(d, e, a, b, c, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9542 | R2(c, d, e, a, b, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9543 | R2(b, c, d, e, a, 24); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9544 | R2(a, b, c, d, e, 25); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9545 | R2(e, a, b, c, d, 26); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9546 | R2(d, e, a, b, c, 27); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9547 | R2(c, d, e, a, b, 28); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9548 | R2(b, c, d, e, a, 29); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9549 | R2(a, b, c, d, e, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9550 | R2(e, a, b, c, d, 31); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9551 | R2(d, e, a, b, c, 32); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9552 | R2(c, d, e, a, b, 33); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9553 | R2(b, c, d, e, a, 34); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9554 | R2(a, b, c, d, e, 35); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9555 | R2(e, a, b, c, d, 36); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9556 | R2(d, e, a, b, c, 37); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9557 | R2(c, d, e, a, b, 38); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9558 | R2(b, c, d, e, a, 39); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9559 | R3(a, b, c, d, e, 40); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9560 | R3(e, a, b, c, d, 41); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9561 | R3(d, e, a, b, c, 42); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9562 | R3(c, d, e, a, b, 43); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9563 | R3(b, c, d, e, a, 44); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9564 | R3(a, b, c, d, e, 45); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9565 | R3(e, a, b, c, d, 46); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9566 | R3(d, e, a, b, c, 47); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9567 | R3(c, d, e, a, b, 48); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9568 | R3(b, c, d, e, a, 49); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9569 | R3(a, b, c, d, e, 50); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9570 | R3(e, a, b, c, d, 51); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9571 | R3(d, e, a, b, c, 52); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9572 | R3(c, d, e, a, b, 53); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9573 | R3(b, c, d, e, a, 54); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9574 | R3(a, b, c, d, e, 55); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9575 | R3(e, a, b, c, d, 56); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9576 | R3(d, e, a, b, c, 57); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9577 | R3(c, d, e, a, b, 58); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9578 | R3(b, c, d, e, a, 59); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9579 | R4(a, b, c, d, e, 60); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9580 | R4(e, a, b, c, d, 61); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9581 | R4(d, e, a, b, c, 62); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9582 | R4(c, d, e, a, b, 63); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9583 | R4(b, c, d, e, a, 64); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9584 | R4(a, b, c, d, e, 65); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9585 | R4(e, a, b, c, d, 66); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9586 | R4(d, e, a, b, c, 67); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9587 | R4(c, d, e, a, b, 68); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9588 | R4(b, c, d, e, a, 69); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9589 | R4(a, b, c, d, e, 70); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9590 | R4(e, a, b, c, d, 71); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9591 | R4(d, e, a, b, c, 72); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9592 | R4(c, d, e, a, b, 73); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9593 | R4(b, c, d, e, a, 74); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9594 | R4(a, b, c, d, e, 75); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9595 | R4(e, a, b, c, d, 76); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9596 | R4(d, e, a, b, c, 77); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9597 | R4(c, d, e, a, b, 78); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9598 | R4(b, c, d, e, a, 79); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9599 | state[0] += a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9600 | state[1] += b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9601 | state[2] += c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9602 | state[3] += d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9603 | state[4] += e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9604 | /* Erase working structures. The order of operations is important, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9605 | * used to ensure that compiler doesn't optimize those out. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9606 | memset(block, 0, sizeof(block)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9607 | a = b = c = d = e = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9608 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9609 | (void) b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9610 | (void) c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9611 | (void) d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9612 | (void) e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9613 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9615 | void cs_sha1_init(cs_sha1_ctx *context) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9616 | context->state[0] = 0x67452301; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9617 | context->state[1] = 0xEFCDAB89; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9618 | context->state[2] = 0x98BADCFE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9619 | context->state[3] = 0x10325476; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9620 | context->state[4] = 0xC3D2E1F0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9621 | context->count[0] = context->count[1] = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9624 | void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9625 | uint32_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9626 | uint32_t i, j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9627 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9628 | j = context->count[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9629 | if ((context->count[0] += len << 3) < j) context->count[1]++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9630 | context->count[1] += (len >> 29); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9631 | j = (j >> 3) & 63; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9632 | if ((j + len) > 63) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9633 | memcpy(&context->buffer[j], data, (i = 64 - j)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9634 | cs_sha1_transform(context->state, context->buffer); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9635 | for (; i + 63 < len; i += 64) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9636 | cs_sha1_transform(context->state, &data[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9637 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9638 | j = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9639 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 9640 | i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9641 | memcpy(&context->buffer[j], &data[i], len - i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9642 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9644 | void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9645 | unsigned i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9646 | unsigned char finalcount[8], c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9648 | for (i = 0; i < 8; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9649 | finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9650 | ((3 - (i & 3)) * 8)) & |
Marko Mikulicic |
0:c0ecb8bf28eb | 9651 | 255); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9652 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9653 | c = 0200; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9654 | cs_sha1_update(context, &c, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9655 | while ((context->count[0] & 504) != 448) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9656 | c = 0000; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9657 | cs_sha1_update(context, &c, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9658 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9659 | cs_sha1_update(context, finalcount, 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9660 | for (i = 0; i < 20; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9661 | digest[i] = |
Marko Mikulicic |
0:c0ecb8bf28eb | 9662 | (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9663 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9664 | memset(context, '\0', sizeof(*context)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9665 | memset(&finalcount, '\0', sizeof(finalcount)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9666 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9668 | void cs_hmac_sha1(const unsigned char *key, size_t keylen, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9669 | const unsigned char *data, size_t datalen, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9670 | unsigned char out[20]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9671 | cs_sha1_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9672 | unsigned char buf1[64], buf2[64], tmp_key[20], i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9674 | if (keylen > sizeof(buf1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9675 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9676 | cs_sha1_update(&ctx, key, keylen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9677 | cs_sha1_final(tmp_key, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9678 | key = tmp_key; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9679 | keylen = sizeof(tmp_key); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9680 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9682 | memset(buf1, 0, sizeof(buf1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9683 | memset(buf2, 0, sizeof(buf2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9684 | memcpy(buf1, key, keylen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9685 | memcpy(buf2, key, keylen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9687 | for (i = 0; i < sizeof(buf1); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9688 | buf1[i] ^= 0x36; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9689 | buf2[i] ^= 0x5c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9690 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9692 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9693 | cs_sha1_update(&ctx, buf1, sizeof(buf1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9694 | cs_sha1_update(&ctx, data, datalen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9695 | cs_sha1_final(out, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9697 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9698 | cs_sha1_update(&ctx, buf2, sizeof(buf2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9699 | cs_sha1_update(&ctx, out, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9700 | cs_sha1_final(out, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9701 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9702 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9703 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9704 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9705 | #line 1 "common/cs_dirent.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9706 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9707 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9708 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 9709 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 9710 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9711 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9712 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 9713 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9714 | /* Amalgamated: #include "common/cs_dirent.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9716 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9717 | * This file contains POSIX opendir/closedir/readdir API implementation |
Marko Mikulicic |
0:c0ecb8bf28eb | 9718 | * for systems which do not natively support it (e.g. Windows). |
Marko Mikulicic |
0:c0ecb8bf28eb | 9719 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9721 | #ifndef MG_FREE |
Marko Mikulicic |
0:c0ecb8bf28eb | 9722 | #define MG_FREE free |
Marko Mikulicic |
0:c0ecb8bf28eb | 9723 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9725 | #ifndef MG_MALLOC |
Marko Mikulicic |
0:c0ecb8bf28eb | 9726 | #define MG_MALLOC malloc |
Marko Mikulicic |
0:c0ecb8bf28eb | 9727 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9729 | #ifdef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9730 | DIR *opendir(const char *name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9731 | DIR *dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9732 | wchar_t wpath[MAX_PATH]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9733 | DWORD attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9735 | if (name == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9736 | SetLastError(ERROR_BAD_ARGUMENTS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9737 | } else if ((dir = (DIR *) MG_MALLOC(sizeof(*dir))) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9738 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9739 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9740 | to_wchar(name, wpath, ARRAY_SIZE(wpath)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9741 | attrs = GetFileAttributesW(wpath); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9742 | if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9743 | (void) wcscat(wpath, L"\\*"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9744 | dir->handle = FindFirstFileW(wpath, &dir->info); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9745 | dir->result.d_name[0] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9746 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9747 | MG_FREE(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9748 | dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9750 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9751 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9752 | return dir; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9753 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9754 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9755 | int closedir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9756 | int result = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9758 | if (dir != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9759 | if (dir->handle != INVALID_HANDLE_VALUE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9760 | result = FindClose(dir->handle) ? 0 : -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9761 | MG_FREE(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9762 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9763 | result = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9764 | SetLastError(ERROR_BAD_ARGUMENTS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9765 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9767 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9768 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9770 | struct dirent *readdir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9771 | struct dirent *result = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9773 | if (dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9774 | if (dir->handle != INVALID_HANDLE_VALUE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9775 | result = &dir->result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9776 | (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9777 | result->d_name, sizeof(result->d_name), NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9778 | NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9780 | if (!FindNextFileW(dir->handle, &dir->info)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9781 | (void) FindClose(dir->handle); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9782 | dir->handle = INVALID_HANDLE_VALUE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9783 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9785 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9786 | SetLastError(ERROR_FILE_NOT_FOUND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9788 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9789 | SetLastError(ERROR_BAD_ARGUMENTS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9790 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9792 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9793 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9794 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9796 | #ifdef CS_ENABLE_SPIFFS |
Marko Mikulicic |
0:c0ecb8bf28eb | 9797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9798 | DIR *opendir(const char *dir_name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9799 | DIR *dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9800 | extern spiffs fs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9802 | if (dir_name != NULL && (dir = (DIR *) malloc(sizeof(*dir))) != NULL && |
Marko Mikulicic |
0:c0ecb8bf28eb | 9803 | SPIFFS_opendir(&fs, (char *) dir_name, &dir->dh) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9804 | free(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9805 | dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9806 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9808 | return dir; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9809 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9811 | int closedir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9812 | if (dir != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9813 | SPIFFS_closedir(&dir->dh); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9814 | free(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9815 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9816 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9817 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9818 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9819 | struct dirent *readdir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9820 | return SPIFFS_readdir(&dir->dh, &dir->de); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9823 | /* SPIFFs doesn't support directory operations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9824 | int rmdir(const char *path) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9825 | (void) path; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9826 | return ENOTDIR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9829 | int mkdir(const char *path, mode_t mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9830 | (void) path; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9831 | (void) mode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9832 | /* for spiffs supports only root dir, which comes from mongoose as '.' */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9833 | return (strlen(path) == 1 && *path == '.') ? 0 : ENOTDIR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9834 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9836 | #endif /* CS_ENABLE_SPIFFS */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9837 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9838 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9840 | /* ISO C requires a translation unit to contain at least one declaration */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9841 | typedef int cs_dirent_dummy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9842 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9843 | #line 1 "common/cs_file.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9844 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9845 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9846 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 9847 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 9848 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9850 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9852 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9853 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9855 | #ifdef CS_MMAP |
Marko Mikulicic |
0:c0ecb8bf28eb | 9856 | #include <fcntl.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9857 | #include <sys/mman.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9858 | #include <sys/stat.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9859 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9861 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 9862 | char *cs_read_file(const char *path, size_t *size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9863 | FILE *fp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9864 | char *data = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9865 | if ((fp = fopen(path, "rb")) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9866 | } else if (fseek(fp, 0, SEEK_END) != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9867 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9868 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9869 | *size = ftell(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9870 | data = (char *) malloc(*size + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9871 | if (data != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9872 | fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9873 | if (fread(data, 1, *size, fp) != *size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9874 | free(data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9875 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9876 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9877 | data[*size] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9878 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9879 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9880 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9881 | return data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9882 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9883 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9885 | #ifdef CS_MMAP |
Marko Mikulicic |
0:c0ecb8bf28eb | 9886 | char *cs_mmap_file(const char *path, size_t *size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9887 | char *r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9888 | int fd = open(path, O_RDONLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9889 | struct stat st; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9890 | if (fd == -1) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9891 | fstat(fd, &st); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9892 | *size = (size_t) st.st_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9893 | r = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9894 | if (r == MAP_FAILED) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9895 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9897 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9898 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9899 | #line 1 "common/cs_strtod.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9900 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9901 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9902 | #include <math.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9904 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9906 | int cs_strncasecmp(const char *s1, const char *s2, size_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9907 | if (n == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9908 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9909 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9911 | while (n-- != 0 && tolower((int) *s1) == tolower((int) *s2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9912 | if (n == 0 || *s1 == '\0' || *s2 == '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9913 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9914 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9915 | s1++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9916 | s2++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9917 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9918 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9919 | return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9922 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9923 | * based on Source: |
Marko Mikulicic |
0:c0ecb8bf28eb | 9924 | * https://github.com/anakod/Sming/blob/master/Sming/system/stringconversion.cpp#L93 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9925 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9927 | double cs_strtod(const char *str, char **endptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9928 | double result = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9929 | char c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9930 | const char *str_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9931 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9932 | unsigned neg : 1; /* result is negative */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9933 | unsigned decimals : 1; /* parsing decimal part */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9934 | unsigned is_exp : 1; /* parsing exponent like e+5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9935 | unsigned is_exp_neg : 1; /* exponent is negative */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9936 | } flags = {0, 0, 0, 0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9937 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9938 | while (isspace((int) *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9939 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9940 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9942 | if (*str == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9943 | /* only space in str? */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9944 | if (endptr != 0) *endptr = (char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9945 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9946 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9948 | /* Handle leading plus/minus signs */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9949 | while (*str == '-' || *str == '+') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9950 | if (*str == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9951 | flags.neg = !flags.neg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9952 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9953 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9954 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9956 | if (cs_strncasecmp(str, "NaN", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9957 | if (endptr != 0) *endptr = (char *) str + 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9958 | return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9959 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9961 | if (cs_strncasecmp(str, "INF", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9962 | str += 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9963 | if (cs_strncasecmp(str, "INITY", 5) == 0) str += 5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9964 | if (endptr != 0) *endptr = (char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9965 | return flags.neg ? -INFINITY : INFINITY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9966 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9968 | str_start = str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9970 | if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9971 | /* base 16 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9972 | str += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9973 | while ((c = tolower((int) *str))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9974 | int d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9975 | if (c >= '0' && c <= '9') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9976 | d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9977 | } else if (c >= 'a' && c <= 'f') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9978 | d = 10 + (c - 'a'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9979 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9980 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9982 | result = 16 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9983 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9984 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9985 | } else if (*str == '0' && (*(str + 1) == 'b' || *(str + 1) == 'B')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9986 | /* base 2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9987 | str += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9988 | while ((c = *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9989 | int d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9990 | if (c != '0' && c != '1') break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9991 | result = 2 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9992 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9993 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9994 | } else if (*str == '0' && *(str + 1) >= '0' && *(str + 1) <= '7') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9995 | /* base 8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9996 | while ((c = *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9997 | int d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9998 | if (c < '0' || c > '7') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9999 | /* fallback to base 10 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10000 | str = str_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10001 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10002 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10003 | result = 8 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10004 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10005 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10008 | if (str == str_start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10009 | /* base 10 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10010 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10011 | /* exponent specified explicitly, like in 3e-5, exponent is -5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10012 | int exp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10013 | /* exponent calculated from dot, like in 1.23, exponent is -2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10014 | int exp_dot = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10015 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10016 | result = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10018 | while ((c = *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10019 | int d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10021 | if (c == '.') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10022 | if (!flags.decimals) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10023 | /* going to parse decimal part */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10024 | flags.decimals = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10025 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10026 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10027 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10028 | /* non-expected dot: assume number data is over */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10029 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10030 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10031 | } else if (c == 'e' || c == 'E') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10032 | /* going to parse exponent part */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10033 | flags.is_exp = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10034 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10035 | c = *str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10037 | /* check sign of the exponent */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10038 | if (c == '-' || c == '+') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10039 | if (c == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10040 | flags.is_exp_neg = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10041 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10042 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10043 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10045 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10046 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10047 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10048 | d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10049 | if (d < 0 || d > 9) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10050 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10051 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10053 | if (!flags.is_exp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10054 | /* apply current digit to the result */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10055 | result = 10 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10056 | if (flags.decimals) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10057 | exp_dot--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10059 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10060 | /* apply current digit to the exponent */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10061 | if (flags.is_exp_neg) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10062 | if (exp > -1022) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10063 | exp = 10 * exp - d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10064 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10065 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10066 | if (exp < 1023) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10067 | exp = 10 * exp + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10068 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10069 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10070 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10072 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10073 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10074 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10075 | exp += exp_dot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10076 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10077 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10078 | * TODO(dfrank): it probably makes sense not to adjust intermediate `double |
Marko Mikulicic |
0:c0ecb8bf28eb | 10079 | * result`, but build double number accordingly to IEEE 754 from taken |
Marko Mikulicic |
0:c0ecb8bf28eb | 10080 | * (integer) mantissa, exponent and sign. That would work faster, and we |
Marko Mikulicic |
0:c0ecb8bf28eb | 10081 | * can avoid any possible round errors. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10082 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10084 | /* if exponent is non-zero, apply it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10085 | if (exp != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10086 | if (exp < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10087 | while (exp++ != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10088 | result /= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10089 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10090 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10091 | while (exp-- != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10092 | result *= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10093 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10094 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10095 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10096 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10098 | if (flags.neg) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10099 | result = -result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10102 | if (endptr != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10103 | *endptr = (char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10104 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10106 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10107 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10108 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10109 | #line 1 "common/coroutine.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10110 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10111 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10112 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10113 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10114 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10115 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10116 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10117 | * Module that provides generic macros and functions to implement "coroutines", |
Marko Mikulicic |
0:c0ecb8bf28eb | 10118 | * i.e. C code that uses `mbuf` as a stack for function calls. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10119 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 10120 | * More info: see the design doc: https://goo.gl/kfcG61 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10121 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10123 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10124 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10125 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10126 | /* Amalgamated: #include "common/coroutine.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10128 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10129 | * Unwinds stack by 1 function. Used when we're returning from function and |
Marko Mikulicic |
0:c0ecb8bf28eb | 10130 | * when an exception is thrown. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10131 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10132 | static void _level_up(struct cr_ctx *p_ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10133 | /* get size of current function's stack data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10134 | size_t locals_size = _CR_CURR_FUNC_LOCALS_SIZE(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10135 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10136 | /* check stacks underflow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10137 | if (_CR_STACK_FID_UND_CHECK(p_ctx, 1 /*fid*/)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10138 | p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10139 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10140 | } else if (_CR_STACK_DATA_UND_CHECK(p_ctx, locals_size)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10141 | p_ctx->status = CR_RES__ERR_STACK_DATA_UNDERFLOW; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10142 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10143 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10145 | /* decrement stacks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10146 | _CR_STACK_DATA_FREE(p_ctx, locals_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10147 | _CR_STACK_FID_FREE(p_ctx, 1 /*fid*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10148 | p_ctx->stack_ret.len = p_ctx->cur_fid_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10150 | /* if we have exception marker here, adjust cur_fid_idx */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10151 | while (CR_CURR_FUNC_C(p_ctx) == CR_FID__TRY_MARKER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10152 | /* check for stack underflow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10153 | if (_CR_STACK_FID_UND_CHECK(p_ctx, _CR_TRY_SIZE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10154 | p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10155 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10156 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10157 | _CR_STACK_FID_FREE(p_ctx, _CR_TRY_SIZE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10158 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10159 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10161 | enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10162 | if (p_ctx->status != CR_RES__OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10163 | goto out; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10164 | } else if (p_ctx->called_fid != CR_FID__NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10165 | /* need to call new function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10167 | size_t locals_size = p_ctx->p_func_descrs[p_ctx->called_fid].locals_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10168 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10169 | * increment stack pointers |
Marko Mikulicic |
0:c0ecb8bf28eb | 10170 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10171 | /* make sure this function has correct `struct cr_func_desc` entry */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10172 | assert(locals_size == p_ctx->call_locals_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10173 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10174 | * make sure we haven't mistakenly included "zero-sized" `.._arg_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 10175 | * structure in `.._locals_t` struct |
Marko Mikulicic |
0:c0ecb8bf28eb | 10176 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 10177 | * By "zero-sized" I mean `cr_zero_size_type_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10178 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10179 | assert(locals_size < sizeof(cr_zero_size_type_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10180 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10181 | _CR_STACK_DATA_ALLOC(p_ctx, locals_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10182 | _CR_STACK_RET_ALLOC(p_ctx, 1 /*fid*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10183 | p_ctx->cur_fid_idx = p_ctx->stack_ret.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10185 | /* copy arguments to our "stack" (and advance locals stack pointer) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10186 | memcpy(p_ctx->stack_data.buf + p_ctx->stack_data.len - locals_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10187 | p_ctx->p_arg_retval, p_ctx->call_arg_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10189 | /* set function id */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10190 | CR_CURR_FUNC_C(p_ctx) = p_ctx->called_fid; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10192 | /* clear called_fid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10193 | p_ctx->called_fid = CR_FID__NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10195 | } else if (p_ctx->need_return) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10196 | /* need to return from the currently running function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10198 | _level_up(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10199 | if (p_ctx->status != CR_RES__OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10200 | goto out; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10203 | p_ctx->need_return = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10204 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10205 | } else if (p_ctx->need_yield) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10206 | /* need to yield */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10207 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10208 | p_ctx->need_yield = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10209 | p_ctx->status = CR_RES__OK_YIELDED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10210 | goto out; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10212 | } else if (p_ctx->thrown_exc != CR_EXC_ID__NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10213 | /* exception was thrown */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10214 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10215 | /* unwind stack until we reach the bottom, or find some try-catch blocks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10216 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10217 | _level_up(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10218 | if (p_ctx->status != CR_RES__OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10219 | goto out; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10220 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10222 | if (_CR_TRY_MARKER(p_ctx) == CR_FID__TRY_MARKER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10223 | /* we have some try-catch here, go to the first catch */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10224 | CR_CURR_FUNC_C(p_ctx) = _CR_TRY_CATCH_FID(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10225 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10226 | } else if (CR_CURR_FUNC_C(p_ctx) == CR_FID__NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10227 | /* we've reached the bottom of the stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10228 | p_ctx->status = CR_RES__ERR_UNCAUGHT_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10229 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10230 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10232 | } while (1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10233 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10234 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10235 | /* remember pointer to current function's locals */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10236 | _CR_CUR_FUNC_LOCALS_UPD(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10238 | out: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10239 | return p_ctx->status; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10240 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10242 | void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10243 | size_t arg_retval_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10244 | const struct cr_func_desc *p_func_descrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10245 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10246 | * make sure we haven't mistakenly included "zero-sized" `.._arg_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 10247 | * structure in `union user_arg_ret`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10248 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 10249 | * By "zero-sized" I mean `cr_zero_size_type_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10250 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10251 | assert(arg_retval_size < sizeof(cr_zero_size_type_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10252 | #ifdef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 10253 | (void) arg_retval_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10254 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10256 | memset(p_ctx, 0x00, sizeof(*p_ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10257 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10258 | p_ctx->p_func_descrs = p_func_descrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10259 | p_ctx->p_arg_retval = p_arg_retval; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10261 | mbuf_init(&p_ctx->stack_data, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10262 | mbuf_init(&p_ctx->stack_ret, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10263 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10264 | mbuf_append(&p_ctx->stack_ret, NULL, 1 /*starting byte for CR_FID__NONE*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10265 | p_ctx->cur_fid_idx = p_ctx->stack_ret.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10267 | _CR_CALL_PREPARE(p_ctx, CR_FID__NONE, 0, 0, CR_FID__NONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10268 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10270 | void cr_context_free(struct cr_ctx *p_ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10271 | mbuf_free(&p_ctx->stack_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10272 | mbuf_free(&p_ctx->stack_ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10273 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10274 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
1:887cf63a2a0b | 10275 | #line 1 "common/platforms/mbed/mbed_libc.c" |
Marko Mikulicic |
1:887cf63a2a0b | 10276 | #endif |
Marko Mikulicic |
1:887cf63a2a0b | 10277 | /* |
Marko Mikulicic |
1:887cf63a2a0b | 10278 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
1:887cf63a2a0b | 10279 | * All rights reserved |
Marko Mikulicic |
1:887cf63a2a0b | 10280 | */ |
Marko Mikulicic |
1:887cf63a2a0b | 10281 | |
Marko Mikulicic |
1:887cf63a2a0b | 10282 | #if CS_PLATFORM == CS_P_MBED |
Marko Mikulicic |
1:887cf63a2a0b | 10283 | |
Marko Mikulicic |
1:887cf63a2a0b | 10284 | long timezone; |
Marko Mikulicic |
1:887cf63a2a0b | 10285 | |
Marko Mikulicic |
1:887cf63a2a0b | 10286 | #endif /* CS_PLATFORM == CS_P_MBED */ |
Marko Mikulicic |
1:887cf63a2a0b | 10287 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10288 | #line 1 "v7/builtin/file.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10289 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10290 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10291 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10292 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10293 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10295 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10296 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10297 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10298 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10299 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10300 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10301 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10302 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10303 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10304 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10305 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10306 | /* Amalgamated: #include "common/cs_dirent.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10308 | #if defined(V7_ENABLE_FILE) && !defined(V7_NO_FS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 10309 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10310 | static const char s_fd_prop[] = "__fd"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10312 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 10313 | static FILE *v7_val_to_file(struct v7 *v7, v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10314 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10315 | return (FILE *) v7_get_ptr(v7, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10316 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10318 | static v7_val_t v7_file_to_val(struct v7 *v7, FILE *file) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10319 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10320 | return v7_mk_foreign(v7, file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10321 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10322 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10323 | static int v7_is_file_type(v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10324 | return v7_is_foreign(val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10325 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10326 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10327 | FILE *v7_val_to_file(struct v7 *v7, v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10328 | v7_val_t v7_file_to_val(struct v7 *v7, FILE *file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10329 | int v7_is_file_type(v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10330 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10332 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10333 | V7_PRIVATE enum v7_err File_eval(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10334 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10335 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10337 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10339 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10340 | const char *s = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10341 | if (s == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10342 | rcode = v7_throwf(v7, "TypeError", "Invalid string"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10343 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10346 | v7_set_gc_enabled(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10347 | rcode = v7_exec_file(v7, s, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10348 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10349 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10350 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10351 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10352 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10353 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10354 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10355 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10357 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10358 | V7_PRIVATE enum v7_err File_exists(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10359 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10360 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10362 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10364 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10365 | const char *fname = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10366 | if (fname != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10367 | struct stat st; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10368 | if (stat(fname, &st) == 0) *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10370 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10371 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10372 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10373 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10375 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10376 | static enum v7_err f_read(struct v7 *v7, int all, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10377 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10378 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10379 | v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10381 | if (v7_is_file_type(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10382 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10383 | char buf[BUFSIZ]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10384 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10385 | FILE *fp = v7_val_to_file(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10387 | /* Read file contents into mbuf */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10388 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10389 | while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10390 | mbuf_append(&m, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10391 | if (!all) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10392 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10394 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10396 | if (m.len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10397 | *res = v7_mk_string(v7, m.buf, m.len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10398 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10399 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10400 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10401 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10402 | *res = v7_mk_string(v7, "", 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10403 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10404 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10405 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10406 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10408 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10409 | V7_PRIVATE enum v7_err File_obj_read(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10410 | return f_read(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10411 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10413 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10414 | V7_PRIVATE enum v7_err File_obj_write(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10415 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10416 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10417 | v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10418 | v7_val_t arg1 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10419 | size_t n, sent = 0, len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10421 | if (v7_is_file_type(arg0) && v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10422 | const char *s = v7_get_string(v7, &arg1, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10423 | FILE *fp = v7_val_to_file(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10424 | while (sent < len && (n = fwrite(s + sent, 1, len - sent, fp)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10425 | sent += n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10427 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10429 | *res = v7_mk_number(v7, sent); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10431 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10432 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10434 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10435 | V7_PRIVATE enum v7_err File_obj_close(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10436 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10437 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10438 | v7_val_t prop = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10439 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10441 | if (v7_is_file_type(prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10442 | ires = fclose(v7_val_to_file(v7, prop)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10445 | *res = v7_mk_number(v7, ires); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10446 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10447 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10448 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10450 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10451 | V7_PRIVATE enum v7_err File_open(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10452 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10453 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10454 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10455 | FILE *fp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10457 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10458 | const char *s1 = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10459 | const char *s2 = "rb"; /* Open files in read mode by default */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10461 | if (v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10462 | s2 = v7_get_cstring(v7, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10463 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10465 | if (s1 == NULL || s2 == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10466 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10467 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10468 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10470 | fp = fopen(s1, s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10471 | if (fp != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10472 | v7_val_t obj = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10473 | v7_val_t file_proto = v7_get( |
Marko Mikulicic |
0:c0ecb8bf28eb | 10474 | v7, v7_get(v7, v7_get_global(v7), "File", ~0), "prototype", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10475 | v7_set_proto(v7, obj, file_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10476 | v7_def(v7, obj, s_fd_prop, sizeof(s_fd_prop) - 1, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 10477 | v7_file_to_val(v7, fp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10478 | *res = obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10479 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10481 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10483 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10484 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10485 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10486 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10489 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10490 | V7_PRIVATE enum v7_err File_read(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10491 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10493 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10494 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10495 | size_t size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10496 | char *data = cs_read_file(path, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10497 | if (data != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10498 | *res = v7_mk_string(v7, data, size, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10499 | free(data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10500 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10501 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10502 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10503 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10504 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10506 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10507 | V7_PRIVATE enum v7_err File_write(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10508 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10509 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10510 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10512 | if (v7_is_string(arg0) && v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10513 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10514 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10515 | const char *buf = v7_get_string(v7, &arg1, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10516 | FILE *fp = fopen(path, "wb+"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10517 | if (fp != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10518 | if (fwrite(buf, 1, len, fp) == len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10519 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10520 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10521 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10522 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10525 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10526 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10528 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10529 | V7_PRIVATE enum v7_err File_rename(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10530 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10531 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10532 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10533 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10535 | if (v7_is_string(arg0) && v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10536 | const char *from = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10537 | const char *to = v7_get_cstring(v7, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10538 | if (from == NULL || to == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10539 | *res = v7_mk_number(v7, ENOENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10540 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10541 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10542 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10543 | ires = rename(from, to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10544 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10546 | *res = v7_mk_number(v7, ires == 0 ? 0 : errno); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10548 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10549 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10550 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10552 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10553 | V7_PRIVATE enum v7_err File_loadJSON(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10554 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10555 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10557 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10558 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10559 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10560 | const char *file_name = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10561 | if (file_name == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10562 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10563 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10565 | rcode = v7_parse_json_file(v7, file_name, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10566 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10567 | /* swallow exception and return undefined */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10568 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10569 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10570 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10571 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10572 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10574 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10575 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10576 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10578 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10579 | V7_PRIVATE enum v7_err File_remove(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10580 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10581 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10582 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10584 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10585 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10586 | if (path == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10587 | *res = v7_mk_number(v7, ENOENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10588 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10589 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10590 | ires = remove(path); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10592 | *res = v7_mk_number(v7, ires == 0 ? 0 : errno); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10594 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10595 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10596 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10597 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10598 | #if V7_ENABLE__File__list |
Marko Mikulicic |
0:c0ecb8bf28eb | 10599 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10600 | V7_PRIVATE enum v7_err File_list(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10601 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10602 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10604 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10605 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10606 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10607 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10608 | struct dirent *dp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10609 | DIR *dirp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10611 | if (path == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10612 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10613 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10615 | if ((dirp = (opendir(path))) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10616 | *res = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10617 | while ((dp = readdir(dirp)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10618 | /* Do not show current and parent dirs */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10619 | if (strcmp((const char *) dp->d_name, ".") == 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 10620 | strcmp((const char *) dp->d_name, "..") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10621 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10623 | /* Add file name to the list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10624 | v7_array_push(v7, *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10625 | v7_mk_string(v7, (const char *) dp->d_name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10626 | strlen((const char *) dp->d_name), 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10627 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10628 | closedir(dirp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10629 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10632 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10633 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10634 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10635 | #endif /* V7_ENABLE__File__list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10637 | void init_file(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10638 | v7_val_t file_obj = v7_mk_object(v7), file_proto = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10639 | v7_set(v7, v7_get_global(v7), "File", 4, file_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10640 | v7_set(v7, file_obj, "prototype", 9, file_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10641 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10642 | v7_set_method(v7, file_obj, "eval", File_eval); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10643 | v7_set_method(v7, file_obj, "exists", File_exists); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10644 | v7_set_method(v7, file_obj, "remove", File_remove); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10645 | v7_set_method(v7, file_obj, "rename", File_rename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10646 | v7_set_method(v7, file_obj, "open", File_open); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10647 | v7_set_method(v7, file_obj, "read", File_read); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10648 | v7_set_method(v7, file_obj, "write", File_write); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10649 | v7_set_method(v7, file_obj, "loadJSON", File_loadJSON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10650 | #if V7_ENABLE__File__list |
Marko Mikulicic |
0:c0ecb8bf28eb | 10651 | v7_set_method(v7, file_obj, "list", File_list); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10652 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10654 | v7_set_method(v7, file_proto, "close", File_obj_close); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10655 | v7_set_method(v7, file_proto, "read", File_obj_read); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10656 | v7_set_method(v7, file_proto, "write", File_obj_write); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10657 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10658 | #if V7_ENABLE__File__require |
Marko Mikulicic |
0:c0ecb8bf28eb | 10659 | v7_def(v7, v7_get_global(v7), "_modcache", ~0, 0, v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10660 | if (v7_exec(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10661 | "function require(m) { " |
Marko Mikulicic |
0:c0ecb8bf28eb | 10662 | " if (m in _modcache) { return _modcache[m]; }" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10663 | " var module = {exports:{}};" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10664 | " File.eval(m);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10665 | " return (_modcache[m] = module.exports)" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10666 | " }", |
Marko Mikulicic |
0:c0ecb8bf28eb | 10667 | NULL) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10668 | /* TODO(mkm): percolate failure */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10669 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10670 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10671 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10672 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10673 | void init_file(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10674 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10675 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10676 | #endif /* NO_LIBC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10677 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10678 | #line 1 "v7/builtin/socket.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10679 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10680 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10681 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10682 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10683 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10684 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10685 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10686 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10687 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10688 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10689 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10690 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10691 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10692 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10694 | #ifdef V7_ENABLE_SOCKET |
Marko Mikulicic |
0:c0ecb8bf28eb | 10695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10696 | #ifdef __WATCOM__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10697 | #define SOMAXCONN 128 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10698 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10700 | #ifndef RECV_BUF_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 10701 | #define RECV_BUF_SIZE 1024 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10702 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10704 | static const char s_sock_prop[] = "__sock"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10706 | static uint32_t s_resolve(struct v7 *v7, v7_val_t ip_address) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10707 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10708 | const char *s = v7_get_string(v7, &ip_address, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10709 | struct hostent *he = gethostbyname(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10710 | return he == NULL ? 0 : *(uint32_t *) he->h_addr_list[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10711 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10713 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10714 | static enum v7_err s_fd_to_sock_obj(struct v7 *v7, sock_t fd, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10715 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10716 | v7_val_t sock_proto = |
Marko Mikulicic |
0:c0ecb8bf28eb | 10717 | v7_get(v7, v7_get(v7, v7_get_global(v7), "Socket", ~0), "prototype", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10719 | *res = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10720 | v7_set_proto(v7, *res, sock_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10721 | v7_def(v7, *res, s_sock_prop, sizeof(s_sock_prop) - 1, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 10722 | v7_mk_number(v7, fd)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10723 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10724 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10725 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10727 | /* Socket.connect(host, port [, is_udp]) -> socket_object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10728 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10729 | V7_PRIVATE enum v7_err Socket_connect(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10730 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10731 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10732 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10733 | v7_val_t arg2 = v7_arg(v7, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10735 | if (v7_is_number(arg1) && v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10736 | struct sockaddr_in sin; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10737 | sock_t sock = |
Marko Mikulicic |
0:c0ecb8bf28eb | 10738 | socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10739 | memset(&sin, 0, sizeof(sin)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10740 | sin.sin_family = AF_INET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10741 | sin.sin_addr.s_addr = s_resolve(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10742 | sin.sin_port = htons((uint16_t) v7_get_double(v7, arg1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10743 | if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10744 | closesocket(sock); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10745 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10746 | rcode = s_fd_to_sock_obj(v7, sock, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10747 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10748 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10751 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10753 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10754 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10755 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10756 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10757 | /* Socket.listen(port [, ip_address [,is_udp]]) -> sock */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10758 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10759 | V7_PRIVATE enum v7_err Socket_listen(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10760 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10761 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10762 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10763 | v7_val_t arg2 = v7_arg(v7, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10764 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10765 | if (v7_is_number(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10766 | struct sockaddr_in sin; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10767 | int on = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10768 | sock_t sock = |
Marko Mikulicic |
0:c0ecb8bf28eb | 10769 | socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10770 | memset(&sin, 0, sizeof(sin)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10771 | sin.sin_family = AF_INET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10772 | sin.sin_port = htons((uint16_t) v7_get_double(v7, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10773 | if (v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10774 | sin.sin_addr.s_addr = s_resolve(v7, arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10775 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10777 | #if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 10778 | /* "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" http://goo.gl/RmrFTm */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10779 | setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &on, sizeof(on)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10780 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10781 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10782 | #if !defined(_WIN32) || defined(SO_EXCLUSIVEADDRUSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 10783 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10784 | * SO_RESUSEADDR is not enabled on Windows because the semantics of |
Marko Mikulicic |
0:c0ecb8bf28eb | 10785 | * SO_REUSEADDR on UNIX and Windows is different. On Windows, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10786 | * SO_REUSEADDR allows to bind a socket to a port without error even if |
Marko Mikulicic |
0:c0ecb8bf28eb | 10787 | * the port is already open by another program. This is not the behavior |
Marko Mikulicic |
0:c0ecb8bf28eb | 10788 | * SO_REUSEADDR was designed for, and leads to hard-to-track failure |
Marko Mikulicic |
0:c0ecb8bf28eb | 10789 | * scenarios. Therefore, SO_REUSEADDR was disabled on Windows unless |
Marko Mikulicic |
0:c0ecb8bf28eb | 10790 | * SO_EXCLUSIVEADDRUSE is supported and set on a socket. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10791 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10792 | setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10793 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10794 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10795 | if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10796 | listen(sock, SOMAXCONN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10797 | rcode = s_fd_to_sock_obj(v7, sock, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10798 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10799 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10800 | closesocket(sock); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10801 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10804 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10805 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10806 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10807 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10808 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10810 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10811 | V7_PRIVATE enum v7_err Socket_accept(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10812 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10813 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10814 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10816 | if (v7_is_number(prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10817 | struct sockaddr_in sin; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10818 | socklen_t len = sizeof(sin); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10819 | sock_t sock = (sock_t) v7_get_double(v7, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10820 | sock_t fd = accept(sock, (struct sockaddr *) &sin, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10821 | if (fd != INVALID_SOCKET) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10822 | rcode = s_fd_to_sock_obj(v7, fd, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10823 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10824 | char *remote_host = inet_ntoa(sin.sin_addr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10825 | v7_set(v7, *res, "remoteHost", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10826 | v7_mk_string(v7, remote_host, ~0, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10828 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10829 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10830 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10831 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10832 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10833 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10834 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10835 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10836 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10837 | /* sock.close() -> errno */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10838 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10839 | V7_PRIVATE enum v7_err Socket_close(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10840 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10841 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10842 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10843 | *res = v7_mk_number(v7, closesocket((sock_t) v7_get_double(v7, prop))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10844 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10845 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10848 | /* sock.recv() -> string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10849 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10850 | static enum v7_err s_recv(struct v7 *v7, int all, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10851 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10852 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10853 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10855 | if (v7_is_number(prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10856 | char buf[RECV_BUF_SIZE]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10857 | sock_t sock = (sock_t) v7_get_double(v7, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10858 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10859 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10861 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10862 | while ((n = recv(sock, buf, sizeof(buf), 0)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10863 | mbuf_append(&m, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10864 | if (!all) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10865 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10867 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10869 | if (n <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10870 | closesocket(sock); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10871 | v7_def(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10872 | V7_DESC_ENUMERABLE(0), v7_mk_number(v7, INVALID_SOCKET)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10873 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10875 | if (m.len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10876 | *res = v7_mk_string(v7, m.buf, m.len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10877 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10878 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10879 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10880 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10882 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10884 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10885 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10888 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10889 | V7_PRIVATE enum v7_err Socket_recvAll(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10890 | return s_recv(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10893 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10894 | V7_PRIVATE enum v7_err Socket_recv(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10895 | return s_recv(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10898 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10899 | V7_PRIVATE enum v7_err Socket_send(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10900 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10901 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10902 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10903 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10904 | size_t len, sent = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10906 | if (v7_is_number(prop) && v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10907 | const char *s = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10908 | sock_t sock = (sock_t) v7_get_double(v7, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10909 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10911 | while (sent < len && (n = send(sock, s + sent, len - sent, 0)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10912 | sent += n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10913 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10914 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10916 | *res = v7_mk_number(v7, sent); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10918 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10920 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10921 | void init_socket(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10922 | v7_val_t socket_obj = v7_mk_object(v7), sock_proto = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10924 | v7_set(v7, v7_get_global(v7), "Socket", 6, socket_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10925 | sock_proto = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10926 | v7_set(v7, socket_obj, "prototype", 9, sock_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10928 | v7_set_method(v7, socket_obj, "connect", Socket_connect); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10929 | v7_set_method(v7, socket_obj, "listen", Socket_listen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10931 | v7_set_method(v7, sock_proto, "accept", Socket_accept); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10932 | v7_set_method(v7, sock_proto, "send", Socket_send); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10933 | v7_set_method(v7, sock_proto, "recv", Socket_recv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10934 | v7_set_method(v7, sock_proto, "recvAll", Socket_recvAll); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10935 | v7_set_method(v7, sock_proto, "close", Socket_close); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10937 | #ifdef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10938 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10939 | WSADATA data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10940 | WSAStartup(MAKEWORD(2, 2), &data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10941 | /* TODO(alashkin): add WSACleanup call */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10942 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10943 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10944 | signal(SIGPIPE, SIG_IGN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10945 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10946 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10947 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10948 | void init_socket(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10949 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10950 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10951 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10952 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10953 | #line 1 "v7/builtin/crypto.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10954 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10955 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10956 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10957 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10958 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10960 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10961 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10963 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10964 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10965 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10966 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10967 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10968 | /* Amalgamated: #include "common/md5.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10969 | /* Amalgamated: #include "common/sha1.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10970 | /* Amalgamated: #include "common/base64.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10971 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10972 | #ifdef V7_ENABLE_CRYPTO |
Marko Mikulicic |
0:c0ecb8bf28eb | 10973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10974 | typedef void (*b64_func_t)(const unsigned char *, int, char *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10975 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10976 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10977 | static enum v7_err b64_transform(struct v7 *v7, b64_func_t func, double mult, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10978 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10979 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10980 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10981 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10983 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10984 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10985 | const char *s = v7_get_string(v7, &arg0, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10986 | char *buf = (char *) malloc(n * mult + 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10987 | if (buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10988 | func((const unsigned char *) s, (int) n, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10989 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10990 | free(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10991 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10994 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10995 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10996 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10997 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10998 | V7_PRIVATE enum v7_err Crypto_base64_decode(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10999 | return b64_transform(v7, (b64_func_t) cs_base64_decode, 0.75, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11002 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11003 | V7_PRIVATE enum v7_err Crypto_base64_encode(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11004 | return b64_transform(v7, cs_base64_encode, 1.5, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11005 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11007 | static void v7_md5(const char *data, size_t len, char buf[16]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11008 | MD5_CTX ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11009 | MD5_Init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11010 | MD5_Update(&ctx, (unsigned char *) data, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11011 | MD5_Final((unsigned char *) buf, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11012 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11014 | static void v7_sha1(const char *data, size_t len, char buf[20]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11015 | cs_sha1_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11016 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11017 | cs_sha1_update(&ctx, (unsigned char *) data, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11018 | cs_sha1_final((unsigned char *) buf, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11019 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11021 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11022 | V7_PRIVATE enum v7_err Crypto_md5(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11023 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11024 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11026 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11027 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11028 | const char *data = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11029 | char buf[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11030 | v7_md5(data, len, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11031 | *res = v7_mk_string(v7, buf, sizeof(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11032 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11033 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11035 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11037 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11038 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11040 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11041 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11042 | V7_PRIVATE enum v7_err Crypto_md5_hex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11043 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11044 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11046 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11047 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11048 | const char *data = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11049 | char hash[16], buf[sizeof(hash) * 2 + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11050 | v7_md5(data, len, hash); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11051 | cs_to_hex(buf, (unsigned char *) hash, sizeof(hash)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11052 | *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11053 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11054 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11055 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11057 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11058 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11059 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11061 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11062 | V7_PRIVATE enum v7_err Crypto_sha1(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11063 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11064 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11066 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11067 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11068 | const char *data = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11069 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11070 | v7_sha1(data, len, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11071 | *res = v7_mk_string(v7, buf, sizeof(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11072 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11073 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11074 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11076 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11077 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11078 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11079 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11080 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11081 | V7_PRIVATE enum v7_err Crypto_sha1_hex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11082 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11083 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11085 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11086 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11087 | const char *data = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11088 | char hash[20], buf[sizeof(hash) * 2 + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11089 | v7_sha1(data, len, hash); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11090 | cs_to_hex(buf, (unsigned char *) hash, sizeof(hash)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11091 | *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11092 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11093 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11094 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11095 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11096 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11097 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11098 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11099 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11100 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11101 | void init_crypto(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11102 | #ifdef V7_ENABLE_CRYPTO |
Marko Mikulicic |
0:c0ecb8bf28eb | 11103 | v7_val_t obj = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11104 | v7_set(v7, v7_get_global(v7), "Crypto", 6, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11105 | v7_set_method(v7, obj, "md5", Crypto_md5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11106 | v7_set_method(v7, obj, "md5_hex", Crypto_md5_hex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11107 | v7_set_method(v7, obj, "sha1", Crypto_sha1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11108 | v7_set_method(v7, obj, "sha1_hex", Crypto_sha1_hex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11109 | v7_set_method(v7, obj, "base64_encode", Crypto_base64_encode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11110 | v7_set_method(v7, obj, "base64_decode", Crypto_base64_decode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11111 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 11112 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11113 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11114 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11115 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11116 | #line 1 "v7/src/varint.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11117 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11118 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11119 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 11120 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 11121 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11123 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11124 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11125 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11126 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11127 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11128 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11129 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11130 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11131 | * Strings in AST are encoded as tuples (length, string). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11132 | * Length is variable-length: if high bit is set in a byte, next byte is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11133 | * Maximum string length with such encoding is 2 ^ (7 * 4) == 256 MiB, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11134 | * assuming that sizeof(size_t) == 4. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11135 | * Small string length (less then 128 bytes) is encoded in 1 byte. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11136 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11137 | V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11138 | size_t i = 0, string_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11140 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11141 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11142 | * Each byte of varint contains 7 bits, in little endian order. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11143 | * MSB is a continuation bit: it tells whether next byte is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11144 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11145 | string_len |= (p[i] & 0x7f) << (7 * i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11146 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11147 | * First we increment i, then check whether it is within boundary and |
Marko Mikulicic |
0:c0ecb8bf28eb | 11148 | * whether decoded byte had continuation bit set. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11149 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11150 | } while (++i < sizeof(size_t) && (p[i - 1] & 0x80)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11151 | *llen = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11153 | return string_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11156 | /* Return number of bytes to store length */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11157 | V7_PRIVATE int calc_llen(size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11158 | int n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11160 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11161 | n++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11162 | } while (len >>= 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11164 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11165 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11167 | V7_PRIVATE int encode_varint(size_t len, unsigned char *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11168 | int i, llen = calc_llen(len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11170 | for (i = 0; i < llen; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11171 | p[i] = (len & 0x7f) | (i < llen - 1 ? 0x80 : 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11172 | len >>= 7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11175 | return llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11176 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11177 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11178 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11179 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11180 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11181 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11182 | #line 1 "v7/src/tokenizer.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11183 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11184 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11185 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 11186 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 11187 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11189 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11190 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11192 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11193 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11195 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11197 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11198 | * NOTE(lsm): Must be in the same order as enum for keywords. See comment |
Marko Mikulicic |
0:c0ecb8bf28eb | 11199 | * for function get_tok() for rationale for that. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11200 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11201 | static const struct v7_vec_const s_keywords[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11202 | V7_VEC("break"), V7_VEC("case"), V7_VEC("catch"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11203 | V7_VEC("continue"), V7_VEC("debugger"), V7_VEC("default"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11204 | V7_VEC("delete"), V7_VEC("do"), V7_VEC("else"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11205 | V7_VEC("false"), V7_VEC("finally"), V7_VEC("for"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11206 | V7_VEC("function"), V7_VEC("if"), V7_VEC("in"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11207 | V7_VEC("instanceof"), V7_VEC("new"), V7_VEC("null"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11208 | V7_VEC("return"), V7_VEC("switch"), V7_VEC("this"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11209 | V7_VEC("throw"), V7_VEC("true"), V7_VEC("try"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11210 | V7_VEC("typeof"), V7_VEC("var"), V7_VEC("void"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11211 | V7_VEC("while"), V7_VEC("with")}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11213 | V7_PRIVATE int is_reserved_word_token(enum v7_tok tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11214 | return tok >= TOK_BREAK && tok <= TOK_WITH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11215 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11216 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11217 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11218 | * Move ptr to the next token, skipping comments and whitespaces. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11219 | * Return number of new line characters detected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11220 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11221 | V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11222 | const char *s = *ptr, *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11223 | int num_lines = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11224 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11225 | while (s != p && s < src_end && *s != '\0' && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11226 | (isspace((unsigned char) *s) || *s == '/')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11227 | p = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11228 | while (s < src_end && *s != '\0' && isspace((unsigned char) *s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11229 | if (*s == '\n') num_lines++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11230 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11232 | if ((s + 1) < src_end && s[0] == '/' && s[1] == '/') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11233 | s += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11234 | while (s < src_end && s[0] != '\0' && s[0] != '\n') s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11235 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11236 | if ((s + 1) < src_end && s[0] == '/' && s[1] == '*') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11237 | s += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11238 | while (s < src_end && s[0] != '\0' && !(s[-1] == '/' && s[-2] == '*')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11239 | if (s[0] == '\n') num_lines++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11240 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11241 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11242 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11243 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11244 | *ptr = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11245 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11246 | return num_lines; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11247 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11249 | /* Advance `s` pointer to the end of identifier */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11250 | static void ident(const char **s, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11251 | const unsigned char *p = (unsigned char *) *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11252 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11253 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11255 | while ((const char *) p < src_end && p[0] != '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11256 | if (p[0] == '$' || p[0] == '_' || isalnum(p[0])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11257 | /* $, _, or any alphanumeric are valid identifier characters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11258 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11259 | } else if ((const char *) (p + 5) < src_end && p[0] == '\\' && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11260 | p[1] == 'u' && isxdigit(p[2]) && isxdigit(p[3]) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11261 | isxdigit(p[4]) && isxdigit(p[5])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11262 | /* Unicode escape, \uXXXX . Could be used like "var \u0078 = 1;" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11263 | p += 6; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11264 | } else if ((n = chartorune(&r, (char *) p)) > 1 && isalpharune(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11265 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11266 | * TODO(dfrank): the chartorune() call above can read `p` past the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11267 | * src_end, so it might crash on incorrect code. The solution would be |
Marko Mikulicic |
0:c0ecb8bf28eb | 11268 | * to modify `chartorune()` to accept src_end argument as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11269 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11270 | /* Unicode alphanumeric character */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11271 | p += n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11272 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11273 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11274 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11275 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11277 | *s = (char *) p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11278 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11280 | static enum v7_tok kw(const char *s, size_t len, int ntoks, enum v7_tok tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11281 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11283 | for (i = 0; i < ntoks; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11284 | if (s_keywords[(tok - TOK_BREAK) + i].len == len && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11285 | memcmp(s_keywords[(tok - TOK_BREAK) + i].p + 1, s + 1, len - 1) == 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11286 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11287 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11289 | return i == ntoks ? TOK_IDENTIFIER : (enum v7_tok)(tok + i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11290 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11292 | static enum v7_tok punct1(const char **s, const char *src_end, int ch1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11293 | enum v7_tok tok1, enum v7_tok tok2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11294 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11295 | if (*s < src_end && **s == ch1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11296 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11297 | return tok1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11298 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11299 | return tok2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11303 | static enum v7_tok punct2(const char **s, const char *src_end, int ch1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11304 | enum v7_tok tok1, int ch2, enum v7_tok tok2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11305 | enum v7_tok tok3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11306 | if ((*s + 2) < src_end && s[0][1] == ch1 && s[0][2] == ch2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11307 | (*s) += 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11308 | return tok2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11309 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11311 | return punct1(s, src_end, ch1, tok1, tok3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11314 | static enum v7_tok punct3(const char **s, const char *src_end, int ch1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11315 | enum v7_tok tok1, int ch2, enum v7_tok tok2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11316 | enum v7_tok tok3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11317 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11318 | if (*s < src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11319 | if (**s == ch1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11320 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11321 | return tok1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11322 | } else if (**s == ch2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11323 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11324 | return tok2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11325 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11326 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11327 | return tok3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11328 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11330 | static void parse_number(const char *s, const char **end, double *num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11331 | *num = cs_strtod(s, (char **) end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11332 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11334 | static enum v7_tok parse_str_literal(const char **p, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11335 | const char *s = *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11336 | int quote = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11338 | if (s < src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11339 | quote = *s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11340 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11342 | /* Scan string literal, handle escape sequences */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11343 | for (; s < src_end && *s != '\0' && *s != quote; s++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11344 | if (*s == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11345 | switch (s[1]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11346 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11347 | case 'f': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11348 | case 'n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11349 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11350 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11351 | case 'v': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11352 | case '\\': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11353 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11354 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11355 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11356 | if (s[1] == quote) s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11357 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11358 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11362 | if (s < src_end && *s == quote) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11363 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11364 | *p = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11365 | return TOK_STRING_LITERAL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11366 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11367 | return TOK_END_OF_INPUT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11368 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11371 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11372 | * This function is the heart of the tokenizer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11373 | * Organized as a giant switch statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11374 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11375 | * Switch statement is by the first character of the input stream. If first |
Marko Mikulicic |
0:c0ecb8bf28eb | 11376 | * character begins with a letter, it could be either keyword or identifier. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11377 | * get_tok() calls ident() which shifts `s` pointer to the end of the word. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11378 | * Now, tokenizer knows that the word begins at `p` and ends at `s`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11379 | * It calls function kw() to scan over the keywords that start with `p[0]` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11380 | * letter. Therefore, keyword tokens and keyword strings must be in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11381 | * same order, to let kw() function work properly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11382 | * If kw() finds a keyword match, it returns keyword token. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11383 | * Otherwise, it returns TOK_IDENTIFIER. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11384 | * NOTE(lsm): `prev_tok` is a previously parsed token. It is needed for |
Marko Mikulicic |
0:c0ecb8bf28eb | 11385 | * correctly parsing regex literals. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11386 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11387 | V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11388 | enum v7_tok prev_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11389 | const char *p = *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11391 | if (p >= src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11392 | return TOK_END_OF_INPUT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11394 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11395 | switch (*p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11396 | /* Letters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11397 | case 'a': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11398 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11399 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11400 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11401 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11402 | return kw(p, *s - p, 1, TOK_BREAK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11403 | case 'c': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11404 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11405 | return kw(p, *s - p, 3, TOK_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11406 | case 'd': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11407 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11408 | return kw(p, *s - p, 4, TOK_DEBUGGER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11409 | case 'e': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11410 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11411 | return kw(p, *s - p, 1, TOK_ELSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11412 | case 'f': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11413 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11414 | return kw(p, *s - p, 4, TOK_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11415 | case 'g': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11416 | case 'h': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11417 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11418 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11419 | case 'i': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11420 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11421 | return kw(p, *s - p, 3, TOK_IF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11422 | case 'j': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11423 | case 'k': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11424 | case 'l': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11425 | case 'm': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11426 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11427 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11428 | case 'n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11429 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11430 | return kw(p, *s - p, 2, TOK_NEW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11431 | case 'o': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11432 | case 'p': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11433 | case 'q': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11434 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11435 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11436 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11437 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11438 | return kw(p, *s - p, 1, TOK_RETURN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11439 | case 's': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11440 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11441 | return kw(p, *s - p, 1, TOK_SWITCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11442 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11443 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11444 | return kw(p, *s - p, 5, TOK_THIS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11445 | case 'u': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11446 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11447 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11448 | case 'v': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11449 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11450 | return kw(p, *s - p, 2, TOK_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11451 | case 'w': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11452 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11453 | return kw(p, *s - p, 2, TOK_WHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11454 | case 'x': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11455 | case 'y': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11456 | case 'z': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11457 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11458 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11460 | case '_': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11461 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11462 | case 'A': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11463 | case 'B': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11464 | case 'C': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11465 | case 'D': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11466 | case 'E': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11467 | case 'F': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11468 | case 'G': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11469 | case 'H': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11470 | case 'I': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11471 | case 'J': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11472 | case 'K': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11473 | case 'L': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11474 | case 'M': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11475 | case 'N': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11476 | case 'O': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11477 | case 'P': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11478 | case 'Q': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11479 | case 'R': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11480 | case 'S': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11481 | case 'T': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11482 | case 'U': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11483 | case 'V': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11484 | case 'W': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11485 | case 'X': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11486 | case 'Y': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11487 | case 'Z': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11488 | case '\\': /* Identifier may start with unicode escape sequence */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11489 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11490 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11492 | /* Numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11493 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11494 | case '1': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11495 | case '2': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11496 | case '3': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11497 | case '4': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11498 | case '5': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11499 | case '6': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11500 | case '7': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11501 | case '8': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11502 | case '9': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11503 | parse_number(p, s, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11504 | return TOK_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11506 | /* String literals */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11507 | case '\'': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11508 | case '"': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11509 | return parse_str_literal(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11511 | /* Punctuators */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11512 | case '=': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11513 | return punct2(s, src_end, '=', TOK_EQ, '=', TOK_EQ_EQ, TOK_ASSIGN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11514 | case '!': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11515 | return punct2(s, src_end, '=', TOK_NE, '=', TOK_NE_NE, TOK_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11517 | case '%': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11518 | return punct1(s, src_end, '=', TOK_REM_ASSIGN, TOK_REM); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11519 | case '*': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11520 | return punct1(s, src_end, '=', TOK_MUL_ASSIGN, TOK_MUL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11521 | case '/': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11522 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11523 | * TOK_DIV, TOK_DIV_ASSIGN, and TOK_REGEX_LITERAL start with `/` char. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11524 | * Division can happen after an expression. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11525 | * In expressions like this: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11526 | * a /= b; c /= d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11527 | * things between slashes is NOT a regex literal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11528 | * The switch below catches all cases where division happens. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11529 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11530 | switch (prev_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11531 | case TOK_CLOSE_CURLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11532 | case TOK_CLOSE_PAREN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11533 | case TOK_CLOSE_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11534 | case TOK_IDENTIFIER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11535 | case TOK_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11536 | return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11537 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11538 | /* Not a division - this is a regex. Scan until closing slash */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11539 | for (p++; p < src_end && *p != '\0' && *p != '\n'; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11540 | if (*p == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11541 | /* Skip escape sequence */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11542 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11543 | } else if (*p == '/') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11544 | /* This is a closing slash */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11545 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11546 | /* Skip regex flags */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11547 | while (*p == 'g' || *p == 'i' || *p == 'm') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11548 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11549 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11550 | *s = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11551 | return TOK_REGEX_LITERAL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11552 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11553 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11554 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11555 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11556 | return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11557 | case '^': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11558 | return punct1(s, src_end, '=', TOK_XOR_ASSIGN, TOK_XOR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11560 | case '+': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11561 | return punct3(s, src_end, '+', TOK_PLUS_PLUS, '=', TOK_PLUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11562 | TOK_PLUS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11563 | case '-': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11564 | return punct3(s, src_end, '-', TOK_MINUS_MINUS, '=', TOK_MINUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11565 | TOK_MINUS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11566 | case '&': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11567 | return punct3(s, src_end, '&', TOK_LOGICAL_AND, '=', TOK_AND_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11568 | TOK_AND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11569 | case '|': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11570 | return punct3(s, src_end, '|', TOK_LOGICAL_OR, '=', TOK_OR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11571 | TOK_OR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11573 | case '<': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11574 | if (*s + 1 < src_end && s[0][1] == '=') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11575 | (*s) += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11576 | return TOK_LE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11577 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11578 | return punct2(s, src_end, '<', TOK_LSHIFT, '=', TOK_LSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11579 | TOK_LT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11580 | case '>': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11581 | if (*s + 1 < src_end && s[0][1] == '=') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11582 | (*s) += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11583 | return TOK_GE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11584 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11585 | if (*s + 3 < src_end && s[0][1] == '>' && s[0][2] == '>' && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11586 | s[0][3] == '=') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11587 | (*s) += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11588 | return TOK_URSHIFT_ASSIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11589 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11590 | if (*s + 2 < src_end && s[0][1] == '>' && s[0][2] == '>') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11591 | (*s) += 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11592 | return TOK_URSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11593 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11594 | return punct2(s, src_end, '>', TOK_RSHIFT, '=', TOK_RSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11595 | TOK_GT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11597 | case '{': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11598 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11599 | return TOK_OPEN_CURLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11600 | case '}': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11601 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11602 | return TOK_CLOSE_CURLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11603 | case '(': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11604 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11605 | return TOK_OPEN_PAREN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11606 | case ')': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11607 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11608 | return TOK_CLOSE_PAREN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11609 | case '[': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11610 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11611 | return TOK_OPEN_BRACKET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11612 | case ']': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11613 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11614 | return TOK_CLOSE_BRACKET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11615 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11616 | switch (*(*s + 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11617 | /* Numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11618 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11619 | case '1': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11620 | case '2': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11621 | case '3': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11622 | case '4': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11623 | case '5': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11624 | case '6': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11625 | case '7': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11626 | case '8': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11627 | case '9': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11628 | parse_number(p, s, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11629 | return TOK_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11631 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11632 | return TOK_DOT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11633 | case ';': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11634 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11635 | return TOK_SEMICOLON; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11636 | case ':': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11637 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11638 | return TOK_COLON; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11639 | case '?': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11640 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11641 | return TOK_QUESTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11642 | case '~': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11643 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11644 | return TOK_TILDA; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11645 | case ',': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11646 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11647 | return TOK_COMMA; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11649 | default: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11650 | /* Handle unicode variables */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11651 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11652 | if (chartorune(&r, *s) > 1 && isalpharune(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11653 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11654 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11655 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11656 | return TOK_END_OF_INPUT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11657 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11658 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11659 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11661 | #ifdef TEST_RUN |
Marko Mikulicic |
0:c0ecb8bf28eb | 11662 | int main(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11663 | const char *src = |
Marko Mikulicic |
0:c0ecb8bf28eb | 11664 | "for (var fo++ = -1; /= <= 1.17; x<<) { == <<=, 'x')} " |
Marko Mikulicic |
0:c0ecb8bf28eb | 11665 | "Infinity %=x<<=2"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11666 | const char *src_end = src + strlen(src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11667 | enum v7_tok tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11668 | double num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11669 | const char *p = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11671 | skip_to_next_tok(&src, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11672 | while ((tok = get_tok(&src, src_end, &num)) != TOK_END_OF_INPUT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11673 | printf("%d [%.*s]\n", tok, (int) (src - p), p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11674 | skip_to_next_tok(&src, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11675 | p = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11677 | printf("%d [%.*s]\n", tok, (int) (src - p), p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11679 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11680 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11681 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11683 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11684 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11685 | #line 1 "v7/src/ast.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11686 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11687 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11688 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 11689 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 11690 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11692 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11693 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11694 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11695 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11696 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11697 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11698 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11699 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11700 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11702 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11704 | #ifdef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 11705 | typedef uint32_t ast_skip_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11706 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 11707 | typedef uint16_t ast_skip_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11708 | #define AST_SKIP_MAX UINT16_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 11709 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11711 | #ifndef V7_DISABLE_AST_TAG_NAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11712 | #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11713 | { (name), (has_varint), (has_inlined), (num_skips), (num_subtrees) } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11714 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 11715 | #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11716 | { (has_varint), (has_inlined), (num_skips), (num_subtrees) } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11717 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11719 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11720 | * The structure of AST nodes cannot be described in portable ANSI C, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11721 | * since they are variable length and packed (unaligned). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11722 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11723 | * Here each node's body is described with a pseudo-C structure notation. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11724 | * The pseudo type `child` represents a variable length byte sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 11725 | * representing a fully serialized child node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11726 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11727 | * `child body[]` represents a sequence of such subtrees. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11728 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11729 | * Pseudo-labels, such as `end:` represent the targets of skip fields |
Marko Mikulicic |
0:c0ecb8bf28eb | 11730 | * with the same name (e.g. `ast_skip_t end`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11731 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11732 | * Skips allow skipping a subtree or sequence of subtrees. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11733 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11734 | * Sequences of subtrees (i.e. `child []`) have to be terminated by a skip: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11735 | * they don't have a termination tag; all nodes whose position is before the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11736 | * skip are part of the sequence. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11737 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11738 | * Skips are encoded as network-byte-order 16-bit offsets counted from the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11739 | * first byte of the node body (i.e. not counting the tag itself). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11740 | * This currently limits the the maximum size of a function body to 64k. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11741 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11742 | * Notes: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11743 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11744 | * - Some nodes contain skips just for performance or because it simplifies |
Marko Mikulicic |
0:c0ecb8bf28eb | 11745 | * the implementation of the interpreter. For example, technically, the FOR |
Marko Mikulicic |
0:c0ecb8bf28eb | 11746 | * node doesn't need the `body` skip in order to be correctly traversed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11747 | * However, being able to quickly skip the `iter` expression is useful |
Marko Mikulicic |
0:c0ecb8bf28eb | 11748 | * also because it allows the interpreter to avoid traversing the expression |
Marko Mikulicic |
0:c0ecb8bf28eb | 11749 | * subtree without evaluating it, just in order to find the next subtree. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11750 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11751 | * - The name `skip` was chosen because `offset` was too overloaded in general |
Marko Mikulicic |
0:c0ecb8bf28eb | 11752 | * and label` is part of our domain model (i.e. JS has a label AST node type). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11753 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11754 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11755 | * So, each node has a mandatory field: *tag* (see `enum ast_tag`), and a |
Marko Mikulicic |
0:c0ecb8bf28eb | 11756 | * number of optional fields. Whether the node has one or another optional |
Marko Mikulicic |
0:c0ecb8bf28eb | 11757 | * field is determined by the *node descriptor*: `struct ast_node_def`. For |
Marko Mikulicic |
0:c0ecb8bf28eb | 11758 | * each node type (i.e. for each element of `enum ast_tag`) there is a |
Marko Mikulicic |
0:c0ecb8bf28eb | 11759 | * corresponding descriptor: see `ast_node_defs`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11760 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11761 | * Optional fields are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11762 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11763 | * - *varint*: a varint-encoded number. At the moment, this field is only used |
Marko Mikulicic |
0:c0ecb8bf28eb | 11764 | * together with the next field: inlined data, and a varint number determines |
Marko Mikulicic |
0:c0ecb8bf28eb | 11765 | * the inlined data length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11766 | * - *inlined data*: a node-specific data. Size of it is determined by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11767 | * previous field: varint. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11768 | * - *skips*: as explained above, these are integer offsets, encoded in |
Marko Mikulicic |
0:c0ecb8bf28eb | 11769 | * big-endian. The number of skips is determined by the node descriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 11770 | * (`struct ast_node_def`). The size of each skip is either 16 or 32 bits, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11771 | * depending on whether the macro `V7_LARGE_AST` is set. The order of skips |
Marko Mikulicic |
0:c0ecb8bf28eb | 11772 | * is determined by the `enum ast_which_skip`. See examples below for |
Marko Mikulicic |
0:c0ecb8bf28eb | 11773 | * clarity. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11774 | * - *subtrees*: child nodes. Some nodes have fixed number of child nodes; in |
Marko Mikulicic |
0:c0ecb8bf28eb | 11775 | * this case, the descriptor has non-zero field `num_subtrees`. Otherwise, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11776 | * `num_subtrees` is zero, and consumer handles child nodes one by one, until |
Marko Mikulicic |
0:c0ecb8bf28eb | 11777 | * the end of the node is reached (end of the node is determined by the `end` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11778 | * skip) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11779 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11780 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11781 | * Examples: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11782 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11783 | * Let's start from the very easy example script: "300;" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11784 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11785 | * Tree looks as follows: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11786 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11787 | * $ ./v7 -e "300;" -t |
Marko Mikulicic |
0:c0ecb8bf28eb | 11788 | * SCRIPT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11789 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11790 | * NUM 300 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11791 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11792 | * Binary data is: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11793 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11794 | * $ ./v7 -e "300;" -b | od -A n -t x1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11795 | * 56 07 41 53 54 56 31 30 00 01 00 09 00 00 13 03 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11796 | * 33 30 30 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11797 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11798 | * Let's break it down and examine: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11799 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11800 | * - 56 07 41 53 54 56 31 30 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11801 | * Just a format prefix: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11802 | * Null-terminated string: `"V\007ASTV10"` (see `BIN_AST_SIGNATURE`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11803 | * - 01 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11804 | * AST tag: `AST_SCRIPT`. As you see in `ast_node_defs` below, node of |
Marko Mikulicic |
0:c0ecb8bf28eb | 11805 | * this type has neither *varint* nor *inlined data* fields, but it has |
Marko Mikulicic |
0:c0ecb8bf28eb | 11806 | * 2 skips: `end` and `next`. `end` is a skip to the end of the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 11807 | * node (`SCRIPT`), and `next` will be explained below. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11808 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11809 | * The size of each skip depends on whether `V7_LARGE_AST` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11810 | * If it is, then size is 32 bit, otherwise it's 16 bit. In this |
Marko Mikulicic |
0:c0ecb8bf28eb | 11811 | * example, we have 16-bit skips. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11812 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11813 | * The order of skips is determined by the `enum ast_which_skip`. If you |
Marko Mikulicic |
0:c0ecb8bf28eb | 11814 | * check, you'll see that `AST_END_SKIP` is 0, and `AST_VAR_NEXT_SKIP` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11815 | * is 1. So, `end` skip fill be the first, and `next` will be the second: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11816 | * - 00 09 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11817 | * `end` skip: 9 bytes. It's the size of the whole `SCRIPT` data. So, if |
Marko Mikulicic |
0:c0ecb8bf28eb | 11818 | * we have an index of the `ASC_SCRIPT` tag, we can just add this skip |
Marko Mikulicic |
0:c0ecb8bf28eb | 11819 | * (9) to this index, and therefore skip over the whole node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11820 | * - 00 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11821 | * `next` skip. `next` actually means "next variable node": since |
Marko Mikulicic |
0:c0ecb8bf28eb | 11822 | * variables are hoisted in JavaScript, when the interpreter starts |
Marko Mikulicic |
0:c0ecb8bf28eb | 11823 | * executing a top-level code or any function, it needs to get a list of |
Marko Mikulicic |
0:c0ecb8bf28eb | 11824 | * all defined variables. The `SCRIPT` node has a "skip" to the first |
Marko Mikulicic |
0:c0ecb8bf28eb | 11825 | * `var` or `function` declaration, which, in turn, has a "skip" to the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11826 | * next one, etc. If there is no next `var` declaration, then 0 is |
Marko Mikulicic |
0:c0ecb8bf28eb | 11827 | * stored. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11828 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11829 | * In our super-simple script, we have no `var` neither `function` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11830 | * declarations, so, this skip is 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11831 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11832 | * Now, the body of our SCRIPT node goes, which contains child nodes: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11833 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11834 | * - 13 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11835 | * AST tag: `AST_NUM`. Look at the `ast_node_defs`, and we'll see that |
Marko Mikulicic |
0:c0ecb8bf28eb | 11836 | * nodes of this type don't have any skips, but they do have the varint |
Marko Mikulicic |
0:c0ecb8bf28eb | 11837 | * field and the inlined data. Here we go: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11838 | * - 03 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11839 | * Varint value: 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11840 | * - 33 30 30 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11841 | * UTF-8 string "300" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11842 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11843 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 11844 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11845 | * The next example is a bit more interesting: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11846 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11847 | * var foo, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11848 | * bar = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11849 | * foo = 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11850 | * var baz = 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11851 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11852 | * Tree: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11853 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11854 | * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -t |
Marko Mikulicic |
0:c0ecb8bf28eb | 11855 | * SCRIPT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11856 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11857 | * VAR |
Marko Mikulicic |
0:c0ecb8bf28eb | 11858 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11859 | * VAR_DECL foo |
Marko Mikulicic |
0:c0ecb8bf28eb | 11860 | * NOP |
Marko Mikulicic |
0:c0ecb8bf28eb | 11861 | * VAR_DECL bar |
Marko Mikulicic |
0:c0ecb8bf28eb | 11862 | * NUM 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11863 | * ASSIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 11864 | * IDENT foo |
Marko Mikulicic |
0:c0ecb8bf28eb | 11865 | * NUM 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11866 | * VAR |
Marko Mikulicic |
0:c0ecb8bf28eb | 11867 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11868 | * VAR_DECL baz |
Marko Mikulicic |
0:c0ecb8bf28eb | 11869 | * NUM 4 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11870 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11871 | * Binary: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11872 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11873 | * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -b | od -A n -t x1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11874 | * 56 07 41 53 54 56 31 30 00 01 00 2d 00 05 02 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11875 | * 12 00 1c 03 03 66 6f 6f 00 03 03 62 61 72 13 01 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11876 | * 31 07 14 03 66 6f 6f 13 01 33 02 00 0c 00 00 03 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11877 | * 03 62 61 7a 13 01 34 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11878 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11879 | * Break it down: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11880 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11881 | * - 56 07 41 53 54 56 31 30 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11882 | * `"V\007ASTV10"` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11883 | * - 01: AST tag: `AST_SCRIPT` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11884 | * - 00 2d: `end` skip: 0x2d = 45 bytes |
Marko Mikulicic |
0:c0ecb8bf28eb | 11885 | * - 00 05: `next` skip: an offset from `AST_SCRIPT` byte to the first |
Marko Mikulicic |
0:c0ecb8bf28eb | 11886 | * `var` declaration. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11887 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11888 | * Now, body of the SCRIPT node begins, which contains child nodes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11889 | * and the first node is the var declaration `var foo, bar=1;`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11890 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11891 | * SCRIPT node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11892 | * - 02: AST tag: `AST_VAR` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11893 | * - 00 12: `end` skip: 18 bytes from tag byte to the end of current node |
Marko Mikulicic |
0:c0ecb8bf28eb | 11894 | * - 00 1c: `next` skip: 28 bytes from tag byte to the next `var` node |
Marko Mikulicic |
0:c0ecb8bf28eb | 11895 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11896 | * The VAR node contains arbitrary number of child nodes, so, consumer |
Marko Mikulicic |
0:c0ecb8bf28eb | 11897 | * takes advantage of the `end` skip. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11898 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11899 | * VAR node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11900 | * - 03: AST tag: `AST_VAR_DECL` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11901 | * - 03: Varint value: 3 (the length of the inlined data: a variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 11902 | *name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11903 | * - 66 6f 6f: UTF-8 string: "foo" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11904 | * - 00: AST tag: `AST_NOP` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11905 | * Since we haven't provided any value to store into `foo`, NOP |
Marko Mikulicic |
0:c0ecb8bf28eb | 11906 | * without any additional data is stored in AST. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11907 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11908 | * - 03: AST tag: `AST_VAR_DECL` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11909 | * - 03: Varint value: 3 (the length of the inlined data: a variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 11910 | *name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11911 | * - 62 61 72: UTF-8 string: "bar" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11912 | * - 13: AST tag: `AST_NUM` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11913 | * - 01: Varint value: 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11914 | * - 31: UTF-8 string "1" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11915 | * VAR body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11916 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11917 | * - 07: AST tag: `AST_ASSIGN` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11918 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11919 | * The ASSIGN node has fixed number of subrees: 2 (lvalue and rvalue), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11920 | * so there's no `end` skip. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11921 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11922 | * ASSIGN node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11923 | * - 14: AST tag: `AST_IDENT` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11924 | * - 03: Varint value: 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11925 | * - 66 6f 6f: UTF-8 string: "foo" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11926 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11927 | * - 13: AST tag: `AST_NUM` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11928 | * - 01: Varint value: 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11929 | * - 33: UTF-8 string: "3" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11930 | * ASSIGN body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11931 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11932 | * - 02: AST tag: `AST_VAR` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11933 | * - 00 0c: `end` skip: 12 bytes from tag byte to the end of current node |
Marko Mikulicic |
0:c0ecb8bf28eb | 11934 | * - 00 00: `next` skip: no more `var` nodes |
Marko Mikulicic |
0:c0ecb8bf28eb | 11935 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11936 | * VAR node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11937 | * - 03: AST tag: `AST_VAR_DECL` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11938 | * - 03: Varint value: 3 (the length of the inlined data: a variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 11939 | *name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11940 | * - 62 61 7a: UTF-8 string: "baz" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11941 | * - 13: AST tag: `AST_NUM` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11942 | * - 01: Varint value: 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11943 | * - 34: UTF-8 string "4" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11944 | * VAR body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11945 | * SCRIPT body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11946 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11947 | * -------------------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 11948 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11950 | const struct ast_node_def ast_node_defs[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11951 | AST_ENTRY("NOP", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11953 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11954 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11955 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11956 | * ast_skip_t first_var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11957 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11958 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11959 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11960 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11961 | AST_ENTRY("SCRIPT", 0, 0, 2, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11962 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11963 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11964 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11965 | * ast_skip_t next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11966 | * child decls[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11967 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11968 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11969 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11970 | AST_ENTRY("VAR", 0, 0, 2, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11971 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11972 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11973 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11974 | * char name[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11975 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11976 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11977 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11978 | AST_ENTRY("VAR_DECL", 1, 1, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11979 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11980 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11981 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11982 | * char name[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11983 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11984 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11985 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11986 | AST_ENTRY("FUNC_DECL", 1, 1, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11987 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11988 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11989 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11990 | * ast_skip_t end_true; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11991 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11992 | * child iftrue[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11993 | * end_true: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11994 | * child iffalse[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11995 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11996 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11997 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11998 | AST_ENTRY("IF", 0, 0, 2, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11999 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12000 | * TODO(mkm) distinguish function expressions |
Marko Mikulicic |
0:c0ecb8bf28eb | 12001 | * from function statements. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12002 | * Function statements behave like vars and need a |
Marko Mikulicic |
0:c0ecb8bf28eb | 12003 | * next field for hoisting. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12004 | * We can also ignore the name for function expressions |
Marko Mikulicic |
0:c0ecb8bf28eb | 12005 | * if it's only needed for debugging. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12006 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 12007 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12008 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12009 | * ast_skip_t first_var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12010 | * ast_skip_t body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12011 | * child name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12012 | * child params[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12013 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12014 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12015 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12016 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12017 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12018 | AST_ENTRY("FUNC", 0, 0, 3, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12019 | AST_ENTRY("ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12020 | AST_ENTRY("REM_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12021 | AST_ENTRY("MUL_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12022 | AST_ENTRY("DIV_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12023 | AST_ENTRY("XOR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12024 | AST_ENTRY("PLUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12025 | AST_ENTRY("MINUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12026 | AST_ENTRY("OR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12027 | AST_ENTRY("AND_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12028 | AST_ENTRY("LSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12029 | AST_ENTRY("RSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12030 | AST_ENTRY("URSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12031 | AST_ENTRY("NUM", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12032 | AST_ENTRY("IDENT", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12033 | AST_ENTRY("STRING", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12034 | AST_ENTRY("REGEX", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12035 | AST_ENTRY("LABEL", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12037 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12038 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12039 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12040 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12041 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12042 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12043 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12044 | AST_ENTRY("SEQ", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12045 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12046 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12047 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12048 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12049 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12050 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12051 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12052 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12053 | AST_ENTRY("WHILE", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12054 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12055 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12056 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12057 | * ast_skip_t cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12058 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12059 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12060 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12061 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12062 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12063 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12064 | AST_ENTRY("DOWHILE", 0, 0, 2, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12065 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12066 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12067 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12068 | * ast_skip_t body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12069 | * child init; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12070 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12071 | * child iter; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12072 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12073 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12074 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12075 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12076 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12077 | AST_ENTRY("FOR", 0, 0, 2, 3), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12078 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12079 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12080 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12081 | * ast_skip_t dummy; // allows to quickly promote a for to a for in |
Marko Mikulicic |
0:c0ecb8bf28eb | 12082 | * child var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12083 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12084 | * child dummy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12085 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12086 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12087 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12088 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12089 | AST_ENTRY("FOR_IN", 0, 0, 2, 3), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12090 | AST_ENTRY("COND", 0, 0, 0, 3), /* struct { child cond, iftrue, iffalse; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12091 | AST_ENTRY("DEBUGGER", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12092 | AST_ENTRY("BREAK", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12094 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12095 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12096 | * child label; // TODO(mkm): inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 12097 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12098 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12099 | AST_ENTRY("LAB_BREAK", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12100 | AST_ENTRY("CONTINUE", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12102 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12103 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12104 | * child label; // TODO(mkm): inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 12105 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12106 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12107 | AST_ENTRY("LAB_CONTINUE", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12108 | AST_ENTRY("RETURN", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12109 | AST_ENTRY("VAL_RETURN", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12110 | AST_ENTRY("THROW", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12112 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12113 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12114 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12115 | * ast_skip_t catch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12116 | * ast_skip_t finally; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12117 | * child try[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12118 | * catch: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12119 | * child var; // TODO(mkm): inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 12120 | * child catch[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12121 | * finally: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12122 | * child finally[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12123 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12124 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12125 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12126 | AST_ENTRY("TRY", 0, 0, 3, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12127 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12128 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12129 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12130 | * ast_skip_t def; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12131 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12132 | * child cases[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12133 | * def: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12134 | * child default?; // optional |
Marko Mikulicic |
0:c0ecb8bf28eb | 12135 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12136 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12137 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12138 | AST_ENTRY("SWITCH", 0, 0, 2, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12139 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12140 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12141 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12142 | * child val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12143 | * child stmts[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12144 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12145 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12146 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12147 | AST_ENTRY("CASE", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12148 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12149 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12150 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12151 | * child stmts[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12152 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12153 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12154 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12155 | AST_ENTRY("DEFAULT", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12156 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12157 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12158 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12159 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12160 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12161 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12162 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12163 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12164 | AST_ENTRY("WITH", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12165 | AST_ENTRY("LOG_OR", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12166 | AST_ENTRY("LOG_AND", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12167 | AST_ENTRY("OR", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12168 | AST_ENTRY("XOR", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12169 | AST_ENTRY("AND", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12170 | AST_ENTRY("EQ", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12171 | AST_ENTRY("EQ_EQ", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12172 | AST_ENTRY("NE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12173 | AST_ENTRY("NE_NE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12174 | AST_ENTRY("LE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12175 | AST_ENTRY("LT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12176 | AST_ENTRY("GE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12177 | AST_ENTRY("GT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12178 | AST_ENTRY("IN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12179 | AST_ENTRY("INSTANCEOF", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12180 | AST_ENTRY("LSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12181 | AST_ENTRY("RSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12182 | AST_ENTRY("URSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12183 | AST_ENTRY("ADD", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12184 | AST_ENTRY("SUB", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12185 | AST_ENTRY("REM", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12186 | AST_ENTRY("MUL", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12187 | AST_ENTRY("DIV", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12188 | AST_ENTRY("POS", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12189 | AST_ENTRY("NEG", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12190 | AST_ENTRY("NOT", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12191 | AST_ENTRY("LOGICAL_NOT", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12192 | AST_ENTRY("VOID", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12193 | AST_ENTRY("DELETE", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12194 | AST_ENTRY("TYPEOF", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12195 | AST_ENTRY("PREINC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12196 | AST_ENTRY("PREDEC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12197 | AST_ENTRY("POSTINC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12198 | AST_ENTRY("POSTDEC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12199 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12200 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12201 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12202 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12203 | * char ident[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12204 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12205 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12206 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12207 | AST_ENTRY("MEMBER", 1, 1, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12208 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12209 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12210 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12211 | * child index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12212 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12213 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12214 | AST_ENTRY("INDEX", 0, 0, 0, 2), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12215 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12216 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12217 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12218 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12219 | * child args[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12220 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12221 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12222 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12223 | AST_ENTRY("CALL", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12224 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12225 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12226 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12227 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12228 | * child args[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12229 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12230 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12231 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12232 | AST_ENTRY("NEW", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12233 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12234 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12235 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12236 | * child elements[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12237 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12238 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12239 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12240 | AST_ENTRY("ARRAY", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12241 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12242 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12243 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12244 | * child props[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12245 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12246 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12247 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12248 | AST_ENTRY("OBJECT", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12249 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12250 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12251 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12252 | * char name[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12253 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12254 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12255 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12256 | AST_ENTRY("PROP", 1, 1, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12257 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12258 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12259 | * child func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12260 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12261 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12262 | AST_ENTRY("GETTER", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12263 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12264 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12265 | * child func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12266 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12267 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12268 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12269 | AST_ENTRY("SETTER", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12270 | AST_ENTRY("THIS", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12271 | AST_ENTRY("TRUE", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12272 | AST_ENTRY("FALSE", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12273 | AST_ENTRY("NULL", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12274 | AST_ENTRY("UNDEF", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12275 | AST_ENTRY("USE_STRICT", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12276 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12278 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12279 | * A flag which is used to mark node's tag byte if the node has line number |
Marko Mikulicic |
0:c0ecb8bf28eb | 12280 | * data encoded (varint after skips). See `ast_get_line_no()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12281 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12282 | #define AST_TAG_LINENO_PRESENT 0x80 |
Marko Mikulicic |
0:c0ecb8bf28eb | 12283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12284 | V7_STATIC_ASSERT(AST_MAX_TAG < 256, ast_tag_should_fit_in_char); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12285 | V7_STATIC_ASSERT(AST_MAX_TAG == ARRAY_SIZE(ast_node_defs), bad_node_defs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12286 | V7_STATIC_ASSERT(AST_MAX_TAG <= AST_TAG_LINENO_PRESENT, bad_AST_LINE_NO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12288 | #if V7_ENABLE_FOOTPRINT_REPORT |
Marko Mikulicic |
0:c0ecb8bf28eb | 12289 | const size_t ast_node_defs_size = sizeof(ast_node_defs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12290 | const size_t ast_node_defs_count = ARRAY_SIZE(ast_node_defs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12291 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12293 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12294 | * Converts a given byte `t` (which should be read from the AST data buffer) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12295 | * into `enum ast_tag`. This function is needed because tag might be marked |
Marko Mikulicic |
0:c0ecb8bf28eb | 12296 | * with the `AST_TAG_LINENO_PRESENT` flag; the returned tag is always unmarked, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12297 | * and if the flag was indeed set, `lineno_present` is set to 1; otherwise |
Marko Mikulicic |
0:c0ecb8bf28eb | 12298 | * it is set to 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12299 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 12300 | * `lineno_present` is allowed to be NULL, if the caller doesn't care of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 12301 | * line number presence. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12302 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12303 | static enum ast_tag uint8_to_tag(uint8_t t, uint8_t *lineno_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12304 | if (t & AST_TAG_LINENO_PRESENT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12305 | t &= ~AST_TAG_LINENO_PRESENT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12306 | if (lineno_present != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12307 | *lineno_present = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12308 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12309 | } else if (lineno_present != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12310 | *lineno_present = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12311 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12312 | return (enum ast_tag) t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12313 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12315 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 12316 | ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12317 | uint8_t t = (uint8_t) tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12318 | const struct ast_node_def *d = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12319 | ast_off_t cur = pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12321 | assert(tag < AST_MAX_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12322 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12323 | mbuf_insert(&a->mbuf, cur, (char *) &t, sizeof(t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12324 | cur += sizeof(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12325 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12326 | mbuf_insert(&a->mbuf, cur, NULL, sizeof(ast_skip_t) * d->num_skips); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12327 | cur += sizeof(ast_skip_t) * d->num_skips; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12328 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12329 | if (d->num_skips) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12330 | ast_set_skip(a, pos + 1, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12331 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12333 | return pos + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12336 | V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12337 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12338 | a->mbuf.buf[tag_off] = tag | (a->mbuf.buf[tag_off] & 0x80); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12339 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12341 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 12342 | V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12343 | ast_off_t ln_off = tag_off + 1 /* tag byte */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12344 | int llen = calc_llen(line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12346 | ast_move_to_inlined_data(a, &ln_off); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12347 | mbuf_insert(&a->mbuf, ln_off, NULL, llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12348 | encode_varint(line_no, (unsigned char *) (a->mbuf.buf + ln_off)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12350 | assert(a->mbuf.buf[tag_off] < AST_MAX_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12351 | a->mbuf.buf[tag_off] |= AST_TAG_LINENO_PRESENT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12352 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12353 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12355 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 12356 | ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12357 | return ast_modify_skip(a, pos, a->mbuf.len, skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12358 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12360 | V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12361 | ast_off_t where, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12362 | enum ast_which_skip skip) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12363 | uint8_t *p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12364 | ast_skip_t delta = where - pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12365 | #ifndef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 12366 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12367 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12368 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12369 | assert(pos <= where); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12371 | #ifndef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 12372 | /* the value of delta overflowed, therefore the ast is not useable */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12373 | if (where - pos > AST_SKIP_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12374 | a->has_overflow = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12375 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12376 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12378 | /* assertion, to be optimizable out */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12379 | assert((int) skip < def->num_skips); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12381 | #ifdef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 12382 | p[0] = delta >> 24; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12383 | p[1] = delta >> 16 & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12384 | p[2] = delta >> 8 & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12385 | p[3] = delta & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12386 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12387 | p[0] = delta >> 8; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12388 | p[1] = delta & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12389 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12390 | return where; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12391 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12393 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 12394 | ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12395 | uint8_t *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12396 | assert(pos + skip * sizeof(ast_skip_t) < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12398 | p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12399 | #ifdef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 12400 | return pos + (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12401 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12402 | return pos + (p[1] | p[0] << 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12403 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12404 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12406 | V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12407 | enum ast_tag ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12408 | assert(*ppos < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12410 | ret = uint8_to_tag(*(a->mbuf.buf + (*ppos)++), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12412 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12413 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12415 | V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12416 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12417 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12418 | assert(*ppos - 1 < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12419 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12420 | ast_move_to_inlined_data(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12422 | /* skip varint + inline data, if present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12423 | if (def->has_varint) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12424 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12425 | size_t slen = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12426 | *ppos += llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12427 | if (def->has_inlined) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12428 | *ppos += slen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12429 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12430 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12431 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12432 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12433 | V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12434 | enum ast_tag tag, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12435 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12436 | const struct ast_node_def *d = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12438 | ast_off_t offset = ast_insert_node(a, pos, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12440 | assert(d->has_inlined); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12442 | embed_string(&a->mbuf, offset + sizeof(ast_skip_t) * d->num_skips, name, len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12443 | EMBSTR_UNESCAPE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12445 | return offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12448 | V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12449 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12450 | * by default we'll return 0, meaning that the AST node does not contain line |
Marko Mikulicic |
0:c0ecb8bf28eb | 12451 | * number data |
Marko Mikulicic |
0:c0ecb8bf28eb | 12452 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12453 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12455 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 12456 | uint8_t lineno_present; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12457 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), &lineno_present); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12459 | if (lineno_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12460 | /* line number is present, so, let's decode it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12461 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12463 | /* skip skips */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12464 | pos += ast_node_defs[tag].num_skips * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12466 | /* get line number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12467 | ret = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12468 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12469 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12470 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12471 | (void) pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12472 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12474 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12475 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12477 | V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12478 | uint8_t lineno_present = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12479 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), &lineno_present); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12480 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12481 | assert(*ppos - 1 < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12483 | /* skip skips */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12484 | *ppos += def->num_skips * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12486 | /* skip line_no, if present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12487 | if (lineno_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12488 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12489 | int line_no = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12490 | *ppos += llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12492 | (void) line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12493 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12494 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12495 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12496 | V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12497 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12498 | assert(pos < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12499 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12500 | ast_move_to_inlined_data(a, &pos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12502 | *n = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12503 | return a->mbuf.buf + pos + llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12504 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12506 | V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12507 | double ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12508 | char *str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12509 | size_t str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12510 | char buf[12]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12511 | char *p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12512 | str = ast_get_inlined_data(a, pos, &str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12513 | assert(str + str_len <= a->mbuf.buf + a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12514 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12515 | if (str_len > sizeof(buf) - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12516 | p = (char *) malloc(str_len + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12517 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12518 | strncpy(p, str, str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12519 | p[str_len] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12520 | ret = cs_strtod(p, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12521 | if (p != buf) free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12522 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12525 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 12526 | static void comment_at_depth(FILE *fp, const char *fmt, int depth, ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12527 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12528 | STATIC char buf[256]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12529 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12530 | va_start(ap, depth); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12532 | c_vsnprintf(buf, sizeof(buf), fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12533 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12534 | for (i = 0; i < depth; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12535 | fprintf(fp, " "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12536 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12537 | fprintf(fp, "/* [%s] */\n", buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12538 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12539 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12540 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12541 | V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12542 | enum ast_tag tag = ast_fetch_tag(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12543 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12544 | ast_off_t skips = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12545 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12546 | ast_move_to_children(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12548 | for (i = 0; i < def->num_subtrees; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12549 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12550 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12552 | if (def->num_skips > AST_END_SKIP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12553 | ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12555 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12556 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12557 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12558 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12559 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12561 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 12562 | V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12563 | int depth) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12564 | enum ast_tag tag = ast_fetch_tag(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12565 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12566 | ast_off_t skips = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12567 | size_t slen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12568 | int i, llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12570 | for (i = 0; i < depth; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12571 | fprintf(fp, " "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12572 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12574 | #ifndef V7_DISABLE_AST_TAG_NAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12575 | fprintf(fp, "%s", def->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12576 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12577 | fprintf(fp, "TAG_%d", tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12578 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12580 | if (def->has_inlined) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12581 | ast_off_t pos_tmp = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12582 | ast_move_to_inlined_data(a, &pos_tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12584 | slen = decode_varint((unsigned char *) a->mbuf.buf + pos_tmp, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12585 | fprintf(fp, " %.*s\n", (int) slen, a->mbuf.buf + pos_tmp + llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12586 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12587 | fprintf(fp, "\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12588 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12589 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12590 | ast_move_to_children(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12592 | for (i = 0; i < def->num_subtrees; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12593 | ast_dump_tree(fp, a, ppos, depth + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12594 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12595 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12596 | if (ast_node_defs[tag].num_skips) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12597 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12598 | * first skip always encodes end of the last children sequence. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12599 | * so unless we care how the subtree sequences are grouped together |
Marko Mikulicic |
0:c0ecb8bf28eb | 12600 | * (and we currently don't) we can just read until the end of that skip. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12601 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12602 | ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12604 | comment_at_depth(fp, "...", depth + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12605 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12606 | int s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12607 | for (s = ast_node_defs[tag].num_skips - 1; s > 0; s--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12608 | if (*ppos == ast_get_skip(a, skips, (enum ast_which_skip) s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12609 | comment_at_depth(fp, "%d ->", depth + 1, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12610 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12611 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12612 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12613 | ast_dump_tree(fp, a, ppos, depth + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12614 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12615 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12616 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12617 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12618 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12619 | V7_PRIVATE void ast_init(struct ast *ast, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12620 | mbuf_init(&ast->mbuf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12621 | ast->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12622 | ast->has_overflow = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12623 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12624 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12625 | V7_PRIVATE void ast_optimize(struct ast *ast) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12626 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12627 | * leave one trailing byte so that literals can be |
Marko Mikulicic |
0:c0ecb8bf28eb | 12628 | * null terminated on the fly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12629 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12630 | mbuf_resize(&ast->mbuf, ast->mbuf.len + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12631 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12633 | V7_PRIVATE void ast_free(struct ast *ast) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12634 | mbuf_free(&ast->mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12635 | ast->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12636 | ast->has_overflow = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12637 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12638 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12639 | V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12640 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12641 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12642 | if (a->refcnt != 0) a->refcnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12644 | if (a->refcnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12645 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12646 | v7->function_arena_ast_size -= a->mbuf.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12647 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12648 | ast_free(a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12649 | free(a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12650 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12651 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12652 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12653 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12654 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12655 | #line 1 "v7/src/bcode.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 12656 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12657 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12658 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 12659 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 12660 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12661 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12662 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12663 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12664 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12665 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12666 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12667 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12668 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12669 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12670 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12671 | /* Amalgamated: #include "v7/src/shdata.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12673 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12674 | * TODO(dfrank): implement `bcode_serialize_*` more generically, so that they |
Marko Mikulicic |
0:c0ecb8bf28eb | 12675 | * can write to buffer instead of a `FILE`. Then, remove a need for mmap here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12676 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12677 | #if CS_PLATFORM == CS_P_UNIX |
Marko Mikulicic |
0:c0ecb8bf28eb | 12678 | #include <sys/mman.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 12679 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12680 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12681 | #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12682 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12683 | static const char *op_names[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12684 | "DROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12685 | "DUP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12686 | "2DUP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12687 | "SWAP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12688 | "STASH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12689 | "UNSTASH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12690 | "SWAP_DROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12691 | "PUSH_UNDEFINED", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12692 | "PUSH_NULL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12693 | "PUSH_THIS", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12694 | "PUSH_TRUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12695 | "PUSH_FALSE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12696 | "PUSH_ZERO", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12697 | "PUSH_ONE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12698 | "PUSH_LIT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12699 | "NOT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12700 | "LOGICAL_NOT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12701 | "NEG", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12702 | "POS", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12703 | "ADD", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12704 | "SUB", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12705 | "REM", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12706 | "MUL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12707 | "DIV", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12708 | "LSHIFT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12709 | "RSHIFT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12710 | "URSHIFT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12711 | "OR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12712 | "XOR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12713 | "AND", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12714 | "EQ_EQ", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12715 | "EQ", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12716 | "NE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12717 | "NE_NE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12718 | "LT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12719 | "LE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12720 | "GT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12721 | "GE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12722 | "INSTANCEOF", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12723 | "TYPEOF", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12724 | "IN", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12725 | "GET", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12726 | "SET", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12727 | "SET_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12728 | "GET_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12729 | "SAFE_GET_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12730 | "JMP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12731 | "JMP_TRUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12732 | "JMP_FALSE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12733 | "JMP_TRUE_DROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12734 | "JMP_IF_CONTINUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12735 | "CREATE_OBJ", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12736 | "CREATE_ARR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12737 | "PUSH_PROP_ITER_CTX", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12738 | "NEXT_PROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12739 | "FUNC_LIT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12740 | "CALL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12741 | "NEW", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12742 | "CHECK_CALL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12743 | "RET", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12744 | "DELETE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12745 | "DELETE_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12746 | "TRY_PUSH_CATCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12747 | "TRY_PUSH_FINALLY", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12748 | "TRY_PUSH_LOOP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12749 | "TRY_PUSH_SWITCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12750 | "TRY_POP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12751 | "AFTER_FINALLY", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12752 | "THROW", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12753 | "BREAK", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12754 | "CONTINUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12755 | "ENTER_CATCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12756 | "EXIT_CATCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12757 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12758 | /* clang-format on */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12760 | V7_STATIC_ASSERT(OP_MAX == ARRAY_SIZE(op_names), bad_op_names); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12761 | V7_STATIC_ASSERT(OP_MAX <= _OP_LINE_NO, bad_OP_LINE_NO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12762 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12764 | static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode, FILE *out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12765 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12766 | static size_t bcode_ops_append(struct bcode_builder *bbuilder, const void *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12767 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12768 | size_t ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12769 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12770 | bbuilder->v7->bcode_ops_size -= bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12771 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12772 | ret = mbuf_append(&bbuilder->ops, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12773 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12774 | bbuilder->v7->bcode_ops_size += bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12775 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12776 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12777 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12779 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12780 | * Initialize bcode builder. The `bcode` should be already initialized by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 12781 | * caller, and should be empty (i.e. should not own any ops, literals, etc) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12782 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 12783 | * TODO(dfrank) : probably make `bcode_builder_init()` to initialize `bcode` |
Marko Mikulicic |
0:c0ecb8bf28eb | 12784 | * as well |
Marko Mikulicic |
0:c0ecb8bf28eb | 12785 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12786 | V7_PRIVATE void bcode_builder_init(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12787 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12788 | struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12789 | memset(bbuilder, 0x00, sizeof(*bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12790 | bbuilder->v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12791 | bbuilder->bcode = bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12793 | mbuf_init(&bbuilder->ops, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12794 | mbuf_init(&bbuilder->lit, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12797 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12798 | * Finalize bcode builder: propagate data to the bcode and transfer the |
Marko Mikulicic |
0:c0ecb8bf28eb | 12799 | * ownership from builder to bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 12800 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12801 | V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12802 | mbuf_trim(&bbuilder->ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12803 | bbuilder->bcode->ops.p = bbuilder->ops.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12804 | bbuilder->bcode->ops.len = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12805 | mbuf_init(&bbuilder->ops, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12806 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12807 | mbuf_trim(&bbuilder->lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12808 | bbuilder->bcode->lit.p = bbuilder->lit.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12809 | bbuilder->bcode->lit.len = bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12810 | mbuf_init(&bbuilder->lit, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12812 | memset(bbuilder, 0x00, sizeof(*bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12813 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12815 | #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12816 | V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12817 | char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12818 | char *p = *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12820 | assert(*p < OP_MAX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12821 | fprintf(f, "%zu: %s", (size_t)(p - bcode->ops.p), op_names[(uint8_t) *p]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12822 | switch (*p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12823 | case OP_PUSH_LIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12824 | case OP_SAFE_GET_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12825 | case OP_GET_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12826 | case OP_SET_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12827 | size_t idx = bcode_get_varint(&p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12828 | fprintf(f, "(%lu): ", (unsigned long) idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12829 | v7_fprint(f, v7, ((val_t *) bcode->lit.p)[idx]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12830 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12831 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12832 | case OP_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12833 | case OP_NEW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12834 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12835 | fprintf(f, "(%d)", *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12836 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12837 | case OP_JMP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12838 | case OP_JMP_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12839 | case OP_JMP_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12840 | case OP_JMP_TRUE_DROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12841 | case OP_JMP_IF_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12842 | case OP_TRY_PUSH_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12843 | case OP_TRY_PUSH_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12844 | case OP_TRY_PUSH_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12845 | case OP_TRY_PUSH_SWITCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12846 | bcode_off_t target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12847 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12848 | memcpy(&target, p, sizeof(target)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12849 | fprintf(f, "(%lu)", (unsigned long) target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12850 | p += sizeof(target) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12851 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12852 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12853 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12854 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12855 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12856 | fprintf(f, "\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12857 | *ops = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12859 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12861 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 12862 | V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12863 | char *p = bcode_end_names(bcode->ops.p, bcode->names_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12864 | char *end = bcode->ops.p + bcode->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12865 | for (; p < end; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12866 | dump_op(v7, f, bcode, &p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12867 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12868 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12869 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12871 | V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12872 | void *filename, uint8_t filename_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12873 | memset(bcode, 0x00, sizeof(*bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12874 | bcode->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12875 | bcode->args_cnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12876 | bcode->strict_mode = strict_mode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12877 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12878 | bcode->filename = filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12879 | bcode->filename_in_rom = filename_in_rom; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12880 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12881 | (void) filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12882 | (void) filename_in_rom; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12883 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12884 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12886 | V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12887 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12888 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12889 | if (!bcode->ops_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12890 | v7->bcode_ops_size -= bcode->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12893 | v7->bcode_lit_total_size -= bcode->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12894 | if (bcode->deserialized) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12895 | v7->bcode_lit_deser_size -= bcode->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12897 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12899 | if (!bcode->ops_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12900 | free(bcode->ops.p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12901 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12902 | memset(&bcode->ops, 0x00, sizeof(bcode->ops)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12904 | free(bcode->lit.p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12905 | memset(&bcode->lit, 0x00, sizeof(bcode->lit)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12907 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12908 | if (!bcode->filename_in_rom && bcode->filename != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12909 | shdata_release((struct shdata *) bcode->filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12910 | bcode->filename = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12911 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12912 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12913 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12914 | bcode->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12917 | V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12918 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12919 | if (!b->frozen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12920 | b->refcnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12921 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12924 | V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12925 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12926 | if (b->frozen) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12928 | assert(b->refcnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12929 | if (b->refcnt != 0) b->refcnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12931 | if (b->refcnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12932 | bcode_free(v7, b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12933 | free(b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12934 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12935 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12937 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12938 | V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12939 | const char *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12940 | if (bcode->filename_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12941 | ret = (const char *) bcode->filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12942 | } else if (bcode->filename != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12943 | ret = (const char *) shdata_get_payload((struct shdata *) bcode->filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12944 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12945 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12946 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12947 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12948 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12949 | V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12950 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12951 | dst->filename_in_rom = src->filename_in_rom; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12952 | dst->filename = src->filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12954 | if (src->filename != NULL && !src->filename_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12955 | shdata_retain((struct shdata *) dst->filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12956 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12957 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12958 | (void) dst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12959 | (void) src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12960 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12961 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12963 | V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12964 | bcode_ops_append(bbuilder, &op, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12965 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12967 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 12968 | V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12969 | int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12970 | int offset = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12971 | bcode_add_varint(bbuilder, (line_no << 1) | 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12972 | bbuilder->ops.buf[offset] = msb_lsb_swap(bbuilder->ops.buf[offset]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12973 | assert(bbuilder->ops.buf[offset] & _OP_LINE_NO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12974 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12975 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12976 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12977 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12978 | * Appends varint-encoded integer to the `ops` mbuf |
Marko Mikulicic |
0:c0ecb8bf28eb | 12979 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12980 | V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12981 | int k = calc_llen(value); /* Calculate how many bytes length takes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12982 | int offset = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12984 | /* Allocate buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12985 | bcode_ops_append(bbuilder, NULL, k); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12987 | /* Write value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12988 | encode_varint(value, (unsigned char *) bbuilder->ops.buf + offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12989 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12991 | V7_PRIVATE size_t bcode_get_varint(char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12992 | size_t ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12993 | int len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12994 | (*ops)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12995 | ret = decode_varint((unsigned char *) *ops, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12996 | *ops += len - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12997 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12998 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13000 | static int bcode_is_inline_string(struct v7 *v7, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13001 | uint64_t tag = val & V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13002 | if (v7->is_precompiling && v7_is_string(val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13003 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13004 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13005 | return tag == V7_TAG_STRING_I || tag == V7_TAG_STRING_5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13008 | static int bcode_is_inline_func(struct v7 *v7, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13009 | return (v7->is_precompiling && is_js_function(val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13010 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13012 | static int bcode_is_inline_regexp(struct v7 *v7, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13013 | return (v7->is_precompiling && v7_is_regexp(v7, val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13014 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13015 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13016 | V7_PRIVATE lit_t bcode_add_lit(struct bcode_builder *bbuilder, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13017 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13018 | memset(&lit, 0, sizeof(lit)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13020 | if (bcode_is_inline_string(bbuilder->v7, val) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 13021 | bcode_is_inline_func(bbuilder->v7, val) || v7_is_number(val) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 13022 | bcode_is_inline_regexp(bbuilder->v7, val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13023 | /* literal should be inlined (it's `bcode_op_lit()` who does this) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13024 | lit.mode = LIT_MODE__INLINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13025 | lit.v.inline_val = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13026 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13027 | /* literal will now be added to the literal table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13028 | lit.mode = LIT_MODE__TABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13029 | lit.v.lit_idx = bbuilder->lit.len / sizeof(val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13031 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 13032 | bbuilder->v7->bcode_lit_total_size -= bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13033 | if (bbuilder->bcode->deserialized) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13034 | bbuilder->v7->bcode_lit_deser_size -= bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13035 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13036 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13038 | mbuf_append(&bbuilder->lit, &val, sizeof(val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13040 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13041 | * immediately propagate current lit buffer to the bcode, so that GC will |
Marko Mikulicic |
0:c0ecb8bf28eb | 13042 | * be aware of it |
Marko Mikulicic |
0:c0ecb8bf28eb | 13043 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13044 | bbuilder->bcode->lit.p = bbuilder->lit.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13045 | bbuilder->bcode->lit.len = bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13046 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13047 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 13048 | bbuilder->v7->bcode_lit_total_size += bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13049 | if (bbuilder->bcode->deserialized) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13050 | bbuilder->v7->bcode_lit_deser_size += bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13051 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13052 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13053 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13054 | return lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13055 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13057 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13058 | V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13059 | val_t ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13060 | memcpy(&ret, bcode->lit.p + (size_t) idx * sizeof(ret), sizeof(ret)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13061 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13062 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13063 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13065 | static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13066 | const char *data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13067 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13068 | V7_PRIVATE v7_val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 13069 | bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13070 | struct v7_vec *vec = &bcode->lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13071 | size_t idx = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13072 | switch (idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13073 | case BCODE_INLINE_STRING_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13074 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13075 | size_t len = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13076 | res = v7_mk_string( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13077 | v7, (const char *) *ops + 1 /*skip BCODE_INLINE_STRING_TYPE_TAG*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13078 | len, !bcode->ops_in_rom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13079 | *ops += len + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13080 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13082 | case BCODE_INLINE_NUMBER_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13083 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13084 | memcpy(&res, *ops + 1 /*skip BCODE_INLINE_NUMBER_TYPE_TAG*/, sizeof(res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13085 | *ops += sizeof(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13086 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13087 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13088 | case BCODE_INLINE_FUNC_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13089 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13090 | * Create half-done function: without scope but _with_ prototype. Scope |
Marko Mikulicic |
0:c0ecb8bf28eb | 13091 | * will be set by `bcode_instantiate_function()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13092 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13093 | * The fact that the prototype is already set will make |
Marko Mikulicic |
0:c0ecb8bf28eb | 13094 | * `bcode_instantiate_function()` just set scope on this function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13095 | * instead of creating a new one. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13096 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13097 | val_t res = mk_js_function(v7, NULL, v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13098 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13099 | /* Create bcode in this half-done function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13100 | struct v7_js_function *func = get_js_function_struct(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13102 | func->bcode = (struct bcode *) calloc(1, sizeof(*func->bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13103 | bcode_init(func->bcode, bcode->strict_mode, NULL /* will be set below */, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13104 | 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13105 | bcode_copy_filename_from(func->bcode, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13106 | retain_bcode(v7, func->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13107 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13108 | /* deserialize the function's bcode from `ops` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13109 | *ops = (char *) bcode_deserialize_func( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13110 | v7, func->bcode, *ops + 1 /*skip BCODE_INLINE_FUNC_TYPE_TAG*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13112 | /* decrement *ops, because it will be incremented by `eval_bcode` soon */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13113 | *ops -= 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13115 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13116 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13117 | case BCODE_INLINE_REGEXP_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13118 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 13119 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13120 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13121 | size_t len_src, len_flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13122 | char *buf_src, *buf_flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13123 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13124 | len_src = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13125 | buf_src = *ops + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13126 | *ops += len_src + 1 /* nul term */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13128 | len_flags = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13129 | buf_flags = *ops + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13130 | *ops += len_flags + 1 /* nul term */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13132 | rcode = v7_mk_regexp(v7, buf_src, len_src, buf_flags, len_flags, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13133 | assert(rcode == V7_OK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13134 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13135 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13136 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13137 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 13138 | fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13139 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13140 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13142 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13143 | return ((val_t *) vec->p)[idx - BCODE_MAX_INLINE_TYPE_TAG]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13144 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13145 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13147 | V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13148 | lit_t lit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13149 | bcode_op(bbuilder, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13151 | switch (lit.mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13152 | case LIT_MODE__TABLE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13153 | bcode_add_varint(bbuilder, lit.v.lit_idx + BCODE_MAX_INLINE_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13154 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13156 | case LIT_MODE__INLINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13157 | if (v7_is_string(lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13158 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13159 | const char *s = v7_get_string(bbuilder->v7, &lit.v.inline_val, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13160 | bcode_add_varint(bbuilder, BCODE_INLINE_STRING_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13161 | bcode_add_varint(bbuilder, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13162 | bcode_ops_append(bbuilder, s, len + 1 /* nul term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13163 | } else if (v7_is_number(lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13164 | bcode_add_varint(bbuilder, BCODE_INLINE_NUMBER_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13165 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13166 | * TODO(dfrank): we can save some memory by storing string |
Marko Mikulicic |
0:c0ecb8bf28eb | 13167 | * representation of a number here, instead of wasting 8 bytes for each |
Marko Mikulicic |
0:c0ecb8bf28eb | 13168 | * number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13169 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13170 | * Alternatively, we can add more tags for integers, like |
Marko Mikulicic |
0:c0ecb8bf28eb | 13171 | * `BCODE_INLINE_S08_TYPE_TAG`, `BCODE_INLINE_S16_TYPE_TAG`, etc, since |
Marko Mikulicic |
0:c0ecb8bf28eb | 13172 | * integers are the most common numbers for sure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13173 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13174 | bcode_ops_append(bbuilder, &lit.v.inline_val, sizeof(lit.v.inline_val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13175 | } else if (is_js_function(lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13176 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13177 | * TODO(dfrank): implement `bcode_serialize_*` more generically, so |
Marko Mikulicic |
0:c0ecb8bf28eb | 13178 | * that they can write to buffer instead of a `FILE`. Then, remove this |
Marko Mikulicic |
0:c0ecb8bf28eb | 13179 | * workaround with `CS_PLATFORM == CS_P_UNIX`, `tmpfile()`, etc. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13180 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13181 | #if CS_PLATFORM == CS_P_UNIX |
Marko Mikulicic |
0:c0ecb8bf28eb | 13182 | struct v7_js_function *func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13183 | FILE *fp = tmpfile(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13184 | long len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13185 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13187 | func = get_js_function_struct(lit.v.inline_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13189 | /* we inline functions if only we're precompiling */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13190 | assert(bbuilder->v7->is_precompiling); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13192 | bcode_add_varint(bbuilder, BCODE_INLINE_FUNC_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13193 | bcode_serialize_func(bbuilder->v7, func->bcode, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13195 | fflush(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13197 | len = ftell(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13199 | p = (char *) mmap(NULL, len, PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13201 | bcode_ops_append(bbuilder, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13203 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13204 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13205 | } else if (v7_is_regexp(bbuilder->v7, lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13206 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 13207 | struct v7_regexp *rp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13208 | v7_get_regexp_struct(bbuilder->v7, lit.v.inline_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13209 | bcode_add_varint(bbuilder, BCODE_INLINE_REGEXP_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13210 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13211 | /* append regexp source */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13212 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13213 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13214 | const char *buf = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13215 | v7_get_string(bbuilder->v7, &rp->regexp_string, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13216 | bcode_add_varint(bbuilder, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13217 | bcode_ops_append(bbuilder, buf, len + 1 /* nul term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13218 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13220 | /* append regexp flags */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13221 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13222 | char buf[_V7_REGEXP_MAX_FLAGS_LEN + 1 /* nul term */]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13223 | size_t len = get_regexp_flags_str(bbuilder->v7, rp, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13224 | bcode_add_varint(bbuilder, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13225 | bcode_ops_append(bbuilder, buf, len + 1 /* nul term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13226 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13227 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 13228 | fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13229 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13230 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13231 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13232 | /* invalid type of inlined value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13233 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13234 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13235 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13237 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13238 | /* invalid literal mode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13239 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13240 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13241 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13242 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13244 | V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13245 | bcode_op_lit(bbuilder, OP_PUSH_LIT, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13246 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13248 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 13249 | /*V7_PRIVATE*/ enum v7_err |
Marko Mikulicic |
0:c0ecb8bf28eb | 13250 | bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13251 | size_t *idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13252 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13253 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13254 | size_t ops_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13256 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13257 | * if name length is not provided, assume it's null-terminated and calculate |
Marko Mikulicic |
0:c0ecb8bf28eb | 13258 | * it |
Marko Mikulicic |
0:c0ecb8bf28eb | 13259 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13260 | if (len == ~((size_t) 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13261 | len = strlen(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13262 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13263 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13264 | /* index at which to put name. If not provided, we'll append at the end */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13265 | if (idx != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13266 | ops_index = *idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13267 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13268 | ops_index = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13271 | /* calculate how much varint len will take */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13272 | llen = calc_llen(len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13274 | /* reserve space in `ops` buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13275 | mbuf_insert(&bbuilder->ops, ops_index, NULL, llen + len + 1 /*null-term*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13277 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13278 | char *ops = bbuilder->ops.buf + ops_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13280 | /* put varint len */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13281 | ops += encode_varint(len, (unsigned char *) ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13283 | /* put string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13284 | memcpy(ops, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13285 | ops += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13286 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13287 | /* null-terminate */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13288 | *ops++ = 0x00; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13290 | if (idx != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13291 | *idx = ops - bbuilder->ops.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13292 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13293 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13295 | /* maintain total number of names */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13296 | if (bbuilder->bcode->names_cnt < V7_NAMES_CNT_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13297 | bbuilder->bcode->names_cnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13298 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13299 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Too many local variables"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13302 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13303 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13305 | /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13306 | while (names_cnt--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13307 | ops = bcode_next_name(ops, NULL, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13308 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13309 | return ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13310 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13312 | V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13313 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13314 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13316 | len = decode_varint((unsigned char *) ops, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13318 | ops += llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13320 | if (pname != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13321 | *pname = ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13324 | if (plen != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13325 | *plen = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13326 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13328 | ops += len + 1 /*null-terminator*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13329 | return ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13330 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13332 | V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13333 | char *ops, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13334 | char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13335 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13337 | ops = bcode_next_name(ops, &name, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13339 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13340 | * If `ops` is in RAM, we create owned string, since the string may outlive |
Marko Mikulicic |
0:c0ecb8bf28eb | 13341 | * bcode. Otherwise (`ops` is in ROM), we create foreign string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13342 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13343 | *res = v7_mk_string(v7, name, len, !bcode->ops_in_rom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13345 | return ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13346 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13347 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13348 | V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13349 | return bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13350 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13352 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13353 | * Appends a branch target and returns its location. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13354 | * This location can be updated with bcode_patch_target. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13355 | * To be issued following a JMP_* bytecode |
Marko Mikulicic |
0:c0ecb8bf28eb | 13356 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13357 | V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13358 | bcode_off_t pos = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13359 | bcode_off_t zero = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13360 | bcode_ops_append(bbuilder, &zero, sizeof(bcode_off_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13361 | return pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13362 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13364 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13365 | * Appends an op requiring a branch target. See bcode_add_target. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13366 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13367 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 13368 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 13369 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13370 | /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13371 | uint8_t op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13372 | bcode_op(bbuilder, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13373 | return bcode_add_target(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13374 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13376 | /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13377 | bcode_off_t label, bcode_off_t target) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13378 | memcpy(bbuilder->ops.buf + label, &target, sizeof(target)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13381 | /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13382 | FILE *out) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13383 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13384 | (void) bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13386 | fwrite(BIN_BCODE_SIGNATURE, sizeof(BIN_BCODE_SIGNATURE), 1, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13387 | bcode_serialize_func(v7, bcode, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13390 | static void bcode_serialize_varint(int n, FILE *out) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13391 | unsigned char buf[8]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13392 | int k = calc_llen(n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13393 | encode_varint(n, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13394 | fwrite(buf, k, 1, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13395 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13397 | static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13398 | FILE *out) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13399 | struct v7_vec *vec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13400 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13402 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13403 | * All literals should be inlined into `ops`, so we expect literals table |
Marko Mikulicic |
0:c0ecb8bf28eb | 13404 | * to be empty here |
Marko Mikulicic |
0:c0ecb8bf28eb | 13405 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13406 | assert(bcode->lit.len == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13408 | /* args_cnt */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13409 | bcode_serialize_varint(bcode->args_cnt, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13411 | /* names_cnt */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13412 | bcode_serialize_varint(bcode->names_cnt, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13413 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13414 | /* func_name_present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13415 | bcode_serialize_varint(bcode->func_name_present, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13417 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13418 | * bcode: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13419 | * <varint> // opcodes length |
Marko Mikulicic |
0:c0ecb8bf28eb | 13420 | * <opcode>* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13421 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13422 | vec = &bcode->ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13423 | bcode_serialize_varint(vec->len, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13424 | fwrite(vec->p, vec->len, 1, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13425 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13427 | static size_t bcode_deserialize_varint(const char **data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13428 | size_t ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13429 | int len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13430 | ret = decode_varint((const unsigned char *) (*data), &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13431 | *data += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13432 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13433 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13434 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13435 | static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13436 | const char *data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13437 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13438 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13440 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13442 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13443 | * before deserializing, set the corresponding flag, so that metrics will be |
Marko Mikulicic |
0:c0ecb8bf28eb | 13444 | * updated accordingly |
Marko Mikulicic |
0:c0ecb8bf28eb | 13445 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13446 | bcode->deserialized = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13448 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13449 | * In serialized functions, all literals are inlined into `ops`, so we don't |
Marko Mikulicic |
0:c0ecb8bf28eb | 13450 | * deserialize them here in any way |
Marko Mikulicic |
0:c0ecb8bf28eb | 13451 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13453 | /* get number of args */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13454 | bcode->args_cnt = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13456 | /* get number of names */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13457 | bcode->names_cnt = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13459 | /* get whether the function name is present in `names` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13460 | bcode->func_name_present = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13462 | /* get opcode size */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13463 | size = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13465 | bbuilder.ops.buf = (char *) data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13466 | bbuilder.ops.size = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13467 | bbuilder.ops.len = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13469 | bcode->ops_in_rom = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13471 | data += size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13473 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13474 | return data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13475 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13477 | V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13478 | const char *data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13479 | data = bcode_deserialize_func(v7, bcode, data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13481 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 13482 | #line 1 "v7/src/eval.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 13483 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13484 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13485 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 13486 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 13487 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13489 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13490 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13491 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13492 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13493 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13494 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13495 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13496 | /* Amalgamated: #include "v7/src/compiler.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13497 | /* Amalgamated: #include "v7/src/cyg_profile.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13498 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13499 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13500 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13501 | /* Amalgamated: #include "v7/src/shdata.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13502 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13503 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13504 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13506 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13507 | * Bcode offsets in "try stack" are stored in JS numbers, i.e. in `double`s. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13508 | * Apart from the offset itself, we also need some additional data: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13509 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13510 | * - type of the block that offset represents (`catch`, `finally`, `switch`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13511 | * or some loop) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13512 | * - size of the stack when the block is created (needed when throwing, since |
Marko Mikulicic |
0:c0ecb8bf28eb | 13513 | * if exception is thrown from the middle of the expression, the stack may |
Marko Mikulicic |
0:c0ecb8bf28eb | 13514 | * have any arbitrary length) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13515 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13516 | * We bake all this data into integer part of the double (53 bits) : |
Marko Mikulicic |
0:c0ecb8bf28eb | 13517 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13518 | * - 32 bits: bcode offset |
Marko Mikulicic |
0:c0ecb8bf28eb | 13519 | * - 3 bits: "tag": the type of the block |
Marko Mikulicic |
0:c0ecb8bf28eb | 13520 | * - 16 bits: stack size |
Marko Mikulicic |
0:c0ecb8bf28eb | 13521 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13523 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13524 | * Widths of data parts |
Marko Mikulicic |
0:c0ecb8bf28eb | 13525 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13526 | #define LBLOCK_OFFSET_WIDTH 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13527 | #define LBLOCK_TAG_WIDTH 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13528 | #define LBLOCK_STACK_SIZE_WIDTH 16 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13529 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13530 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13531 | * Shifts of data parts |
Marko Mikulicic |
0:c0ecb8bf28eb | 13532 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13533 | #define LBLOCK_OFFSET_SHIFT (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13534 | #define LBLOCK_TAG_SHIFT (LBLOCK_OFFSET_SHIFT + LBLOCK_OFFSET_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13535 | #define LBLOCK_STACK_SIZE_SHIFT (LBLOCK_TAG_SHIFT + LBLOCK_TAG_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13536 | #define LBLOCK_TOTAL_WIDTH (LBLOCK_STACK_SIZE_SHIFT + LBLOCK_STACK_SIZE_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13538 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13539 | * Masks of data parts |
Marko Mikulicic |
0:c0ecb8bf28eb | 13540 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13541 | #define LBLOCK_OFFSET_MASK \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13542 | ((int64_t)(((int64_t) 1 << LBLOCK_OFFSET_WIDTH) - 1) << LBLOCK_OFFSET_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13543 | #define LBLOCK_TAG_MASK \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13544 | ((int64_t)(((int64_t) 1 << LBLOCK_TAG_WIDTH) - 1) << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13545 | #define LBLOCK_STACK_SIZE_MASK \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13546 | ((int64_t)(((int64_t) 1 << LBLOCK_STACK_SIZE_WIDTH) - 1) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13547 | << LBLOCK_STACK_SIZE_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13548 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13549 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13550 | * Self-check: make sure all the data can fit into double's mantissa |
Marko Mikulicic |
0:c0ecb8bf28eb | 13551 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13552 | #if (LBLOCK_TOTAL_WIDTH > 53) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13553 | #error lblock width is too large, it can't fit into double's mantissa |
Marko Mikulicic |
0:c0ecb8bf28eb | 13554 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13556 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13557 | * Tags that are used for bcode offsets in "try stack" |
Marko Mikulicic |
0:c0ecb8bf28eb | 13558 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13559 | #define LBLOCK_TAG_CATCH ((int64_t) 0x01 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13560 | #define LBLOCK_TAG_FINALLY ((int64_t) 0x02 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13561 | #define LBLOCK_TAG_LOOP ((int64_t) 0x03 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13562 | #define LBLOCK_TAG_SWITCH ((int64_t) 0x04 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13563 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13564 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13565 | * Yields 32-bit bcode offset value |
Marko Mikulicic |
0:c0ecb8bf28eb | 13566 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13567 | #define LBLOCK_OFFSET(v) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13568 | ((bcode_off_t)(((v) &LBLOCK_OFFSET_MASK) >> LBLOCK_OFFSET_SHIFT)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13570 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13571 | * Yields tag value (unshifted, to be compared with macros like |
Marko Mikulicic |
0:c0ecb8bf28eb | 13572 | * `LBLOCK_TAG_CATCH`, etc) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13573 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13574 | #define LBLOCK_TAG(v) ((v) &LBLOCK_TAG_MASK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13576 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13577 | * Yields stack size |
Marko Mikulicic |
0:c0ecb8bf28eb | 13578 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13579 | #define LBLOCK_STACK_SIZE(v) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13580 | (((v) &LBLOCK_STACK_SIZE_MASK) >> LBLOCK_STACK_SIZE_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13582 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13583 | * Yields `int64_t` value to be stored as a JavaScript number |
Marko Mikulicic |
0:c0ecb8bf28eb | 13584 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13585 | #define LBLOCK_ITEM_CREATE(offset, tag, stack_size) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13586 | ((int64_t)(offset) | (tag) | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13587 | (((int64_t)(stack_size)) << LBLOCK_STACK_SIZE_SHIFT)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13589 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13590 | * make sure `bcode_off_t` is just 32-bit, so that it can fit in double |
Marko Mikulicic |
0:c0ecb8bf28eb | 13591 | * with 3-bit tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 13592 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13593 | V7_STATIC_ASSERT((sizeof(bcode_off_t) * 8) == LBLOCK_OFFSET_WIDTH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13594 | wrong_size_of_bcode_off_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13595 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13596 | #define PUSH(v) stack_push(&v7->stack, v) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13597 | #define POP() stack_pop(&v7->stack) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13598 | #define TOS() stack_tos(&v7->stack) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13599 | #define SP() stack_sp(&v7->stack) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13601 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13602 | * Local-to-function block types that we might want to consider when unwinding |
Marko Mikulicic |
0:c0ecb8bf28eb | 13603 | * stack for whatever reason. see `unwind_local_blocks_stack()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13604 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13605 | enum local_block { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13606 | LOCAL_BLOCK_NONE = (0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13607 | LOCAL_BLOCK_CATCH = (1 << 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13608 | LOCAL_BLOCK_FINALLY = (1 << 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13609 | LOCAL_BLOCK_LOOP = (1 << 2), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13610 | LOCAL_BLOCK_SWITCH = (1 << 3), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13611 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13612 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13613 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13614 | * Like `V7_TRY()`, but to be used inside `eval_bcode()` only: you should |
Marko Mikulicic |
0:c0ecb8bf28eb | 13615 | * wrap all calls to cfunctions into `BTRY()` instead of `V7_TRY()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13616 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13617 | * If the provided function returns something other than `V7_OK`, this macro |
Marko Mikulicic |
0:c0ecb8bf28eb | 13618 | * calls `bcode_perform_throw`, which performs bcode stack unwinding. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13619 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13620 | #define BTRY(call) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13621 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13622 | enum v7_err _e = call; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13623 | (void) _you_should_use_BTRY_in_eval_bcode_only; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13624 | if (_e != V7_OK) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13625 | V7_TRY(bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13626 | goto op_done; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13627 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13628 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13630 | V7_PRIVATE void stack_push(struct mbuf *s, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13631 | mbuf_append(s, &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13634 | V7_PRIVATE val_t stack_pop(struct mbuf *s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13635 | assert(s->len >= sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13636 | s->len -= sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13637 | return *(val_t *) (s->buf + s->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13638 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13640 | V7_PRIVATE val_t stack_tos(struct mbuf *s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13641 | assert(s->len >= sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13642 | return *(val_t *) (s->buf + s->len - sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13643 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13645 | #ifdef V7_BCODE_TRACE_STACK |
Marko Mikulicic |
0:c0ecb8bf28eb | 13646 | V7_PRIVATE val_t stack_at(struct mbuf *s, size_t idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13647 | assert(s->len >= sizeof(val_t) * idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13648 | return *(val_t *) (s->buf + s->len - sizeof(val_t) - idx * sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13649 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13650 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13652 | V7_PRIVATE int stack_sp(struct mbuf *s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13653 | return s->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13654 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13656 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13657 | * Delete a property with name `name`, `len` from an object `obj`. If the |
Marko Mikulicic |
0:c0ecb8bf28eb | 13658 | * object does not contain own property with the given `name`, moves to `obj`'s |
Marko Mikulicic |
0:c0ecb8bf28eb | 13659 | * prototype, and so on. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13660 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13661 | * If the property is eventually found, it is deleted, and `0` is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13662 | * Otherwise, `-1` is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13663 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13664 | * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13665 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13666 | * See `v7_del()` as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13667 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13668 | static int del_property_deep(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13669 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13670 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13671 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13672 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13673 | for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13674 | int del_res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13675 | if ((del_res = v7_del(v7, obj, name, len)) != -1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13676 | return del_res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13678 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13679 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13680 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13682 | /* Visual studio 2012+ has signbit() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13683 | #if defined(_MSC_VER) && _MSC_VER < 1700 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13684 | static int signbit(double x) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13685 | double s = _copysign(1, x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13686 | return s < 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13687 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13688 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13690 | static double b_int_bin_op(enum opcode op, double a, double b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13691 | int32_t ia = isnan(a) || isinf(a) ? 0 : (int32_t)(int64_t) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13692 | int32_t ib = isnan(b) || isinf(b) ? 0 : (int32_t)(int64_t) b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13694 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13695 | case OP_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13696 | return (int32_t)((uint32_t) ia << ((uint32_t) ib & 31)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13697 | case OP_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13698 | return ia >> ((uint32_t) ib & 31); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13699 | case OP_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13700 | return (uint32_t) ia >> ((uint32_t) ib & 31); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13701 | case OP_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13702 | return ia | ib; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13703 | case OP_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13704 | return ia ^ ib; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13705 | case OP_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13706 | return ia & ib; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13707 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13708 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13709 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13710 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13711 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13713 | static double b_num_bin_op(enum opcode op, double a, double b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13714 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13715 | * For certain operations, the result is always NaN if either of arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 13716 | * is NaN |
Marko Mikulicic |
0:c0ecb8bf28eb | 13717 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13718 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13719 | case OP_ADD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13720 | case OP_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13721 | case OP_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13722 | case OP_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13723 | case OP_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13724 | if (isnan(a) || isnan(b)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13725 | return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13726 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13727 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13728 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13729 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13732 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13733 | case OP_ADD: /* simple fixed width nodes with no payload */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13734 | return a + b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13735 | case OP_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13736 | return a - b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13737 | case OP_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13738 | if (b == 0 || isnan(b) || isnan(a) || isinf(b) || isinf(a)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13739 | return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13740 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13741 | return (int) a % (int) b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13742 | case OP_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13743 | return a * b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13744 | case OP_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13745 | if (b == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13746 | if (a == 0) return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13747 | return (!signbit(a) == !signbit(b)) ? INFINITY : -INFINITY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13748 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13749 | return a / b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13750 | case OP_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13751 | case OP_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13752 | case OP_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13753 | case OP_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13754 | case OP_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13755 | case OP_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13756 | return b_int_bin_op(op, a, b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13757 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13758 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13759 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13760 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13761 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13762 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13763 | static int b_bool_bin_op(enum opcode op, double a, double b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13764 | #ifdef V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 13765 | if (isnan(a) || isnan(b)) return op == OP_NE || op == OP_NE_NE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13766 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13768 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13769 | case OP_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13770 | case OP_EQ_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13771 | return a == b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13772 | case OP_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13773 | case OP_NE_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13774 | return a != b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13775 | case OP_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13776 | return a < b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13777 | case OP_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13778 | return a <= b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13779 | case OP_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13780 | return a > b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13781 | case OP_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13782 | return a >= b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13783 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13784 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13786 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13789 | static bcode_off_t bcode_get_target(char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13790 | bcode_off_t target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13791 | (*ops)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13792 | memcpy(&target, *ops, sizeof(target)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13793 | *ops += sizeof(target) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13794 | return target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13797 | struct bcode_registers { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13798 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13799 | * TODO(dfrank): make it contain `struct v7_call_frame_bcode *` |
Marko Mikulicic |
0:c0ecb8bf28eb | 13800 | * and use `bcode_ops` in-place, or probably drop the `bcode_registers` |
Marko Mikulicic |
0:c0ecb8bf28eb | 13801 | * whatsoever |
Marko Mikulicic |
0:c0ecb8bf28eb | 13802 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13803 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13804 | char *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13805 | char *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13806 | unsigned int need_inc_ops : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13807 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13809 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13810 | * If returning from function implicitly, then set return value to `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13811 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13812 | * And if function was called as a constructor, then make sure returned |
Marko Mikulicic |
0:c0ecb8bf28eb | 13813 | * value is an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13814 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13815 | static void bcode_adjust_retval(struct v7 *v7, uint8_t is_explicit_return) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13816 | if (!is_explicit_return) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13817 | /* returning implicitly: set return value to `undefined` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13818 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13819 | PUSH(V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13820 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13821 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13822 | if (v7->call_stack->is_constructor && !v7_is_object(TOS())) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13823 | /* constructor is going to return non-object: replace it with `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13824 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13825 | PUSH(v7_get_this(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13826 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13829 | static void bcode_restore_registers(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13830 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13831 | r->bcode = bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13832 | r->ops = bcode->ops.p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13833 | r->end = r->ops + bcode->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13835 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13836 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13837 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13838 | V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13839 | uint8_t type_mask) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13840 | struct v7_call_frame_base *ret = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13842 | while (ret != NULL && !(ret->type_mask & type_mask)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13843 | ret = ret->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13846 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13849 | static struct v7_call_frame_private *find_call_frame_private(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13850 | return (struct v7_call_frame_private *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13851 | v7, V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13852 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13854 | static struct v7_call_frame_bcode *find_call_frame_bcode(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13855 | return (struct v7_call_frame_bcode *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13856 | v7, V7_CALL_FRAME_MASK_BCODE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13857 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13859 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13860 | static struct v7_call_frame_cfunc *find_call_frame_cfunc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13861 | return (struct v7_call_frame_cfunc *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13862 | v7, V7_CALL_FRAME_MASK_CFUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13864 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13866 | static struct v7_call_frame_base *create_call_frame(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13867 | size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13868 | struct v7_call_frame_base *call_frame_base = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13869 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13870 | call_frame_base = (struct v7_call_frame_base *) calloc(1, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13872 | /* save previous call frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13873 | call_frame_base->prev = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13875 | /* by default, inherit line_no from the previous frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13876 | if (v7->call_stack != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13877 | call_frame_base->line_no = v7->call_stack->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13878 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13880 | return call_frame_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13881 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13882 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13883 | static void init_call_frame_private(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13884 | struct v7_call_frame_private *call_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13885 | val_t scope) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13886 | /* make a snapshot of the current state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13887 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13888 | struct v7_call_frame_private *cf = find_call_frame_private(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13889 | if (cf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13890 | cf->stack_size = v7->stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13892 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13894 | /* set a type flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13895 | call_frame->base.type_mask |= V7_CALL_FRAME_MASK_PRIVATE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13897 | /* fill the new frame with data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13898 | call_frame->vals.scope = scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13899 | /* `try_stack` will be lazily created in `eval_try_push()`*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13900 | call_frame->vals.try_stack = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13901 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13903 | static void init_call_frame_bcode(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13904 | struct v7_call_frame_bcode *call_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13905 | char *prev_bcode_ops, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13906 | val_t this_obj, val_t scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13907 | uint8_t is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13908 | init_call_frame_private(v7, &call_frame->base, scope); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13910 | /* make a snapshot of the current state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13911 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13912 | struct v7_call_frame_bcode *cf = find_call_frame_bcode(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13913 | if (cf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13914 | cf->bcode_ops = prev_bcode_ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13916 | /* remember thrown value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13917 | cf->vals.thrown_error = v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13918 | cf->base.base.is_thrown = v7->is_thrown; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13922 | /* set a type flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13923 | call_frame->base.base.type_mask |= V7_CALL_FRAME_MASK_BCODE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13925 | /* fill the new frame with data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13926 | call_frame->bcode = bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13927 | call_frame->vals.this_obj = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13928 | call_frame->base.base.is_constructor = is_constructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13929 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13931 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13932 | * Create new bcode call frame object and fill it with data |
Marko Mikulicic |
0:c0ecb8bf28eb | 13933 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13934 | static void append_call_frame_bcode(struct v7 *v7, char *prev_bcode_ops, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13935 | struct bcode *bcode, val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13936 | val_t scope, uint8_t is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13937 | struct v7_call_frame_bcode *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13938 | (struct v7_call_frame_bcode *) create_call_frame(v7, sizeof(*call_frame)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13940 | init_call_frame_bcode(v7, call_frame, prev_bcode_ops, bcode, this_obj, scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13941 | is_constructor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13943 | v7->call_stack = &call_frame->base.base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13944 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13946 | static void append_call_frame_private(struct v7 *v7, val_t scope) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13947 | struct v7_call_frame_private *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13948 | (struct v7_call_frame_private *) create_call_frame(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13949 | sizeof(*call_frame)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13950 | init_call_frame_private(v7, call_frame, scope); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13952 | v7->call_stack = &call_frame->base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13953 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13955 | static void append_call_frame_cfunc(struct v7 *v7, val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13956 | v7_cfunction_t *cfunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13957 | struct v7_call_frame_cfunc *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13958 | (struct v7_call_frame_cfunc *) create_call_frame(v7, sizeof(*call_frame)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13960 | /* set a type flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13961 | call_frame->base.type_mask |= V7_CALL_FRAME_MASK_CFUNC; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13963 | /* fill the new frame with data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13964 | call_frame->cfunc = cfunc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13965 | call_frame->vals.this_obj = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13967 | v7->call_stack = &call_frame->base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13968 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13970 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13971 | * The caller's bcode object is needed because we have to restore literals |
Marko Mikulicic |
0:c0ecb8bf28eb | 13972 | * and `end` registers. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13973 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13974 | * TODO(mkm): put this state on a return stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 13975 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13976 | * Caller of bcode_perform_call is responsible for owning `call_frame` |
Marko Mikulicic |
0:c0ecb8bf28eb | 13977 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13978 | static enum v7_err bcode_perform_call(struct v7 *v7, v7_val_t scope_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13979 | struct v7_js_function *func, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13980 | struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13981 | val_t this_object, char *ops, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13982 | uint8_t is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13983 | /* new scope_frame will inherit from the function's scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13984 | obj_prototype_set(v7, get_object_struct(scope_frame), &func->scope->base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13985 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13986 | /* create new `call_frame` which will replace `v7->call_stack` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13987 | append_call_frame_bcode(v7, r->ops + 1, func->bcode, this_object, scope_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13988 | is_constructor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13989 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13990 | bcode_restore_registers(v7, func->bcode, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13991 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13992 | /* adjust `ops` since names were already read from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13993 | r->ops = ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13995 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13996 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13998 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13999 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14000 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14001 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14002 | * Apply data from the "private" call frame, typically after some other frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 14003 | * was just unwound. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14004 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14005 | * The `call_frame` may actually be `NULL`, if the top frame was unwound. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14006 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14007 | static void apply_frame_private(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14008 | struct v7_call_frame_private *call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14009 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14010 | * Adjust data stack length (restore saved). |
Marko Mikulicic |
0:c0ecb8bf28eb | 14011 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14012 | * If `call_frame` is NULL, it means that the last call frame was just |
Marko Mikulicic |
0:c0ecb8bf28eb | 14013 | * unwound, and hence the data stack size should be 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14014 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14015 | size_t stack_size = (call_frame != NULL ? call_frame->stack_size : 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14016 | assert(stack_size <= v7->stack.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14017 | v7->stack.len = stack_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14020 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14021 | * Apply data from the "bcode" call frame, typically after some other frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 14022 | * was just unwound. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14023 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14024 | * The `call_frame` may actually be `NULL`, if the top frame was unwound; but |
Marko Mikulicic |
0:c0ecb8bf28eb | 14025 | * in this case, `r` must be `NULL` too, by design. See inline comment below. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14026 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14027 | static void apply_frame_bcode(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14028 | struct v7_call_frame_bcode *call_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14029 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14030 | if (r != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14031 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14032 | * Note: if `r` is non-NULL, then `call_frame` should be non-NULL as well, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14033 | * by design. If this invariant is violated, it means that |
Marko Mikulicic |
0:c0ecb8bf28eb | 14034 | * `unwind_stack_1level()` is misused. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14035 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14036 | assert(call_frame != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14038 | bcode_restore_registers(v7, call_frame->bcode, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14039 | r->ops = call_frame->bcode_ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14040 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14041 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14042 | * restore thrown value if only there's no new thrown value |
Marko Mikulicic |
0:c0ecb8bf28eb | 14043 | * (otherwise, the new one overrides the previous one) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14044 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14045 | if (!v7->is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14046 | v7->vals.thrown_error = call_frame->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14047 | v7->is_thrown = call_frame->base.base.is_thrown; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14049 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14050 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14052 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14053 | * Unwinds `call_stack` by 1 frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14054 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14055 | * Returns the type of the unwound frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 14056 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14057 | static v7_call_frame_mask_t unwind_stack_1level(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14058 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14059 | v7_call_frame_mask_t type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14060 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14061 | fprintf(stderr, "unwinding stack by 1 level\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14062 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14064 | type_mask = v7->call_stack->type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14066 | /* drop the top frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14067 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14068 | struct v7_call_frame_base *tmp = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14069 | v7->call_stack = v7->call_stack->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14070 | free(tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14071 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14073 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14074 | * depending on the unwound frame type, apply data from the top call frame(s) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14075 | * which are still alive (if any) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14076 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14078 | if (type_mask & V7_CALL_FRAME_MASK_PRIVATE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14079 | apply_frame_private(v7, find_call_frame_private(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14080 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14081 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14082 | if (type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14083 | apply_frame_bcode(v7, find_call_frame_bcode(v7), r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14084 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14085 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14086 | if (type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14087 | /* Nothing to do here at the moment */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14089 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14090 | return type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14091 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14092 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14093 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14094 | * Unwinds local "try stack" (i.e. local-to-current-function stack of nested |
Marko Mikulicic |
0:c0ecb8bf28eb | 14095 | * `try` blocks), looking for local-to-function blocks. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14096 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14097 | * Block types of interest are specified with `wanted_blocks_mask`: it's a |
Marko Mikulicic |
0:c0ecb8bf28eb | 14098 | * bitmask of `enum local_block` values. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14099 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14100 | * Only blocks of specified types will be considered, others will be dropped. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14101 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14102 | * If `restore_stack_size` is non-zero, the `v7->stack.len` will be restored |
Marko Mikulicic |
0:c0ecb8bf28eb | 14103 | * to the value saved when the block was created. This is useful when throwing, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14104 | * since if we throw from the middle of the expression, the stack could have |
Marko Mikulicic |
0:c0ecb8bf28eb | 14105 | * any size. But you probably shouldn't set this flag when breaking and |
Marko Mikulicic |
0:c0ecb8bf28eb | 14106 | * returning, since it may hide real bugs in the opcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14107 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14108 | * Returns id of the block type that control was transferred into, or |
Marko Mikulicic |
0:c0ecb8bf28eb | 14109 | * `LOCAL_BLOCK_NONE` if no appropriate block was found. Note: returned value |
Marko Mikulicic |
0:c0ecb8bf28eb | 14110 | * contains at most 1 block bit; it can't contain multiple bits. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14111 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14112 | static enum local_block unwind_local_blocks_stack( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14113 | struct v7 *v7, struct bcode_registers *r, unsigned int wanted_blocks_mask, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14114 | uint8_t restore_stack_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14115 | val_t arr = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14116 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14117 | enum local_block found_block = LOCAL_BLOCK_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14118 | unsigned long length; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14119 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14120 | tmp_stack_push(&tf, &arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14121 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14122 | arr = find_call_frame_private(v7)->vals.try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14123 | if (v7_is_array(v7, arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14124 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14125 | * pop latest element from "try stack", loop until we need to transfer |
Marko Mikulicic |
0:c0ecb8bf28eb | 14126 | * control there |
Marko Mikulicic |
0:c0ecb8bf28eb | 14127 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14128 | while ((length = v7_array_length(v7, arr)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14129 | /* get latest offset from the "try stack" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14130 | int64_t offset = v7_get_double(v7, v7_array_get(v7, arr, length - 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14131 | enum local_block cur_block = LOCAL_BLOCK_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14132 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14133 | /* get id of the current block type */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14134 | switch (LBLOCK_TAG(offset)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14135 | case LBLOCK_TAG_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14136 | cur_block = LOCAL_BLOCK_CATCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14137 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14138 | case LBLOCK_TAG_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14139 | cur_block = LOCAL_BLOCK_FINALLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14140 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14141 | case LBLOCK_TAG_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14142 | cur_block = LOCAL_BLOCK_LOOP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14143 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14144 | case LBLOCK_TAG_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14145 | cur_block = LOCAL_BLOCK_SWITCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14146 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14147 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14148 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14149 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14150 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14151 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14152 | if (cur_block & wanted_blocks_mask) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14153 | /* need to transfer control to this offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14154 | r->ops = r->bcode->ops.p + LBLOCK_OFFSET(offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14155 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14156 | fprintf(stderr, "transferring to block #%d: %u\n", (int) cur_block, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14157 | (unsigned int) LBLOCK_OFFSET(offset)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14158 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14159 | found_block = cur_block; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14160 | /* if needed, restore stack size to the saved value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14161 | if (restore_stack_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14162 | v7->stack.len = LBLOCK_STACK_SIZE(offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14163 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14164 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14165 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14166 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14167 | fprintf(stderr, "skipped block #%d: %u\n", (int) cur_block, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14168 | (unsigned int) LBLOCK_OFFSET(offset)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14169 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14170 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14171 | * since we don't need to control transfer there, just pop |
Marko Mikulicic |
0:c0ecb8bf28eb | 14172 | * it from the "try stack" |
Marko Mikulicic |
0:c0ecb8bf28eb | 14173 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14174 | v7_array_del(v7, arr, length - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14175 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14176 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14177 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14178 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14179 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14180 | return found_block; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14181 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14182 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14183 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14184 | * Perform break, if there is a `finally` block in effect, transfer |
Marko Mikulicic |
0:c0ecb8bf28eb | 14185 | * control there. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14186 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14187 | static void bcode_perform_break(struct v7 *v7, struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14188 | enum local_block found; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14189 | unsigned int mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14190 | v7->is_breaking = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14191 | if (v7->is_continuing) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14192 | mask = LOCAL_BLOCK_LOOP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14193 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14194 | mask = LOCAL_BLOCK_LOOP | LOCAL_BLOCK_SWITCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14197 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14198 | * Keep unwinding until we find local block of interest. We should not |
Marko Mikulicic |
0:c0ecb8bf28eb | 14199 | * encounter any "function" frames; only "private" frames are allowed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14200 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14201 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14202 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14203 | * Try to unwind local "try stack", considering only `finally` and `break`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14204 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14205 | found = unwind_local_blocks_stack(v7, r, mask | LOCAL_BLOCK_FINALLY, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14206 | if (found == LOCAL_BLOCK_NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14207 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14208 | * no blocks found: this may happen if only the `break` or `continue` has |
Marko Mikulicic |
0:c0ecb8bf28eb | 14209 | * occurred inside "private" frame. So, unwind this frame, make sure it |
Marko Mikulicic |
0:c0ecb8bf28eb | 14210 | * is indeed a "private" frame, and keep unwinding local blocks. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14211 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14212 | v7_call_frame_mask_t frame_type_mask = unwind_stack_1level(v7, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14213 | assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14214 | (void) frame_type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14215 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14216 | /* found some block to transfer control into, stop unwinding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14217 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14218 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14219 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14220 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14221 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14222 | * upon exit of a finally block we'll reenter here if is_breaking is true. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14223 | * See OP_AFTER_FINALLY. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14224 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14225 | if (found == LOCAL_BLOCK_FINALLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14226 | v7->is_breaking = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14227 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14229 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14230 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14232 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14233 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14234 | * Perform return, but if there is a `finally` block in effect, transfer |
Marko Mikulicic |
0:c0ecb8bf28eb | 14235 | * control there. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14236 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14237 | * If `take_retval` is non-zero, value to return will be popped from stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 14238 | * (and saved into `v7->vals.returned_value`), otherwise, it won't ae affected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14239 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14240 | static enum v7_err bcode_perform_return(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14241 | struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14242 | int take_retval) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14243 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14244 | * We should either take retval from the stack, or some value should already |
Marko Mikulicic |
0:c0ecb8bf28eb | 14245 | * de pending to return |
Marko Mikulicic |
0:c0ecb8bf28eb | 14246 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14247 | assert(take_retval || v7->is_returned); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14249 | if (take_retval) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14250 | /* taking return value from stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14251 | v7->vals.returned_value = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14252 | v7->is_returned = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14253 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14254 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14255 | * returning (say, from `finally`) dismisses any errors that are eeing |
Marko Mikulicic |
0:c0ecb8bf28eb | 14256 | * thrown at the moment as well |
Marko Mikulicic |
0:c0ecb8bf28eb | 14257 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14258 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14259 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14260 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14262 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14263 | * Keep unwinding until we unwound "function" frame, or found some `finally` |
Marko Mikulicic |
0:c0ecb8bf28eb | 14264 | * block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14265 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14266 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14267 | /* Try to unwind local "try stack", considering only `finally` blocks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14268 | if (unwind_local_blocks_stack(v7, r, (LOCAL_BLOCK_FINALLY), 0) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 14269 | LOCAL_BLOCK_NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14270 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14271 | * no `finally` blocks were found, so, unwind stack by 1 level, and see |
Marko Mikulicic |
0:c0ecb8bf28eb | 14272 | * if it's a "function" frame. If not, will keep unwinding. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14273 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14274 | if (unwind_stack_1level(v7, r) & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14275 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14276 | * unwound frame is a "function" frame, so, push returned value to |
Marko Mikulicic |
0:c0ecb8bf28eb | 14277 | * stack, and stop unwinding |
Marko Mikulicic |
0:c0ecb8bf28eb | 14278 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14279 | PUSH(v7->vals.returned_value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14280 | v7->is_returned = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14281 | v7->vals.returned_value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14283 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14284 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14285 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14286 | /* found `finally` block, so, stop unwinding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14287 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14288 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14289 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14290 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14291 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14292 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14293 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14294 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14297 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14298 | * Perform throw inside `eval_bcode()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14299 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14300 | * If `take_thrown_value` is non-zero, value to return will be popped from |
Marko Mikulicic |
0:c0ecb8bf28eb | 14301 | * stack (and saved into `v7->vals.thrown_error`), otherwise, it won't be |
Marko Mikulicic |
0:c0ecb8bf28eb | 14302 | * affected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14303 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14304 | * Returns `V7_OK` if thrown exception was caught, `V7_EXEC_EXCEPTION` |
Marko Mikulicic |
0:c0ecb8bf28eb | 14305 | * otherwise (in this case, evaluation of current script must be stopped) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14306 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14307 | * When calling this function from `eval_rcode()`, you should wrap this call |
Marko Mikulicic |
0:c0ecb8bf28eb | 14308 | * into the `V7_TRY()` macro. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14309 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14310 | static enum v7_err bcode_perform_throw(struct v7 *v7, struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14311 | int take_thrown_value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14312 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14313 | enum local_block found; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14315 | assert(take_thrown_value || v7->is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14317 | if (take_thrown_value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14318 | v7->vals.thrown_error = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14319 | v7->is_thrown = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14321 | /* Throwing dismisses any pending return values */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14322 | v7->is_returned = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14323 | v7->vals.returned_value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14324 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14325 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14326 | while ((found = unwind_local_blocks_stack( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14327 | v7, r, (LOCAL_BLOCK_CATCH | LOCAL_BLOCK_FINALLY), 1)) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 14328 | LOCAL_BLOCK_NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14329 | if (v7->call_stack != v7->bottom_call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14330 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14331 | fprintf(stderr, "not at the bottom of the stack, going to unwind..\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14332 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14333 | /* not reached bottom of the stack yet, keep unwinding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14334 | unwind_stack_1level(v7, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14335 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14336 | /* reached stack bottom: uncaught exception */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14337 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14338 | fprintf(stderr, "reached stack bottom: uncaught exception\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14339 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14340 | rcode = V7_EXEC_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14341 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14343 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14345 | if (found == LOCAL_BLOCK_CATCH) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14346 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14347 | * we're going to enter `catch` block, so, populate TOS with the thrown |
Marko Mikulicic |
0:c0ecb8bf28eb | 14348 | * value, and clear it in v7 context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14349 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14350 | PUSH(v7->vals.thrown_error); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14351 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14352 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14355 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14356 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14358 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14361 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14362 | * Throws reference error from `eval_bcode()`. Always wrap a call to this |
Marko Mikulicic |
0:c0ecb8bf28eb | 14363 | * function into `V7_TRY()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14364 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14365 | static enum v7_err bcode_throw_reference_error(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14366 | struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14367 | val_t var_name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14368 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14369 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14370 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14371 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14372 | assert(v7_is_string(var_name)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14373 | s = v7_get_string(v7, &var_name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14375 | rcode = v7_throwf(v7, REFERENCE_ERROR, "[%.*s] is not defined", |
Marko Mikulicic |
0:c0ecb8bf28eb | 14376 | (int) name_len, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14377 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14378 | return bcode_perform_throw(v7, r, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14381 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14382 | * Takes a half-done function (either from literal table or deserialized from |
Marko Mikulicic |
0:c0ecb8bf28eb | 14383 | * `ops` inlined data), and returns a ready-to-use function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14384 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14385 | * The actual behaviour depends on whether the half-done function has |
Marko Mikulicic |
0:c0ecb8bf28eb | 14386 | * `prototype` defined. If there's no prototype (i.e. it's `undefined`), then |
Marko Mikulicic |
0:c0ecb8bf28eb | 14387 | * the new function is created, with bcode from a given one. If, however, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14388 | * the prototype is defined, it means that the function was just deserialized |
Marko Mikulicic |
0:c0ecb8bf28eb | 14389 | * from `ops`, so we only need to set `scope` on it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14390 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14391 | * Assumes `func` is owned by the caller. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14392 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14393 | static val_t bcode_instantiate_function(struct v7 *v7, val_t func) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14394 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14395 | struct v7_generic_object *scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14396 | struct v7_js_function *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14397 | assert(is_js_function(func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14398 | f = get_js_function_struct(func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14400 | scope = get_generic_object_struct(get_scope(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14402 | if (v7_is_undefined(v7_get(v7, func, "prototype", 9))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14403 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14404 | * Function's `prototype` is `undefined`: it means that the function is |
Marko Mikulicic |
0:c0ecb8bf28eb | 14405 | * created by the compiler and is stored in the literal table. We have to |
Marko Mikulicic |
0:c0ecb8bf28eb | 14406 | * create completely new function |
Marko Mikulicic |
0:c0ecb8bf28eb | 14407 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14408 | struct v7_js_function *rf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14410 | res = mk_js_function(v7, scope, v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14412 | /* Copy and retain bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14413 | rf = get_js_function_struct(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14414 | rf->bcode = f->bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14415 | retain_bcode(v7, rf->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14416 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14417 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14418 | * Function's `prototype` is NOT `undefined`: it means that the function is |
Marko Mikulicic |
0:c0ecb8bf28eb | 14419 | * deserialized from inline `ops` data, and we just need to set scope on |
Marko Mikulicic |
0:c0ecb8bf28eb | 14420 | * it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14421 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14422 | res = func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14423 | f->scope = scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14424 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14426 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14427 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14429 | /** |
Marko Mikulicic |
0:c0ecb8bf28eb | 14430 | * Call C function `func` with given `this_object` and array of arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 14431 | * `args`. `func` should be a C function pointer, not C function object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14432 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14433 | static enum v7_err call_cfunction(struct v7 *v7, val_t func, val_t this_object, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14434 | val_t args, uint8_t is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14435 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14436 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14437 | uint8_t saved_inhibit_gc = v7->inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14438 | val_t saved_arguments = v7->vals.arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14439 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14440 | v7_cfunction_t *cfunc = get_cfunction_ptr(v7, func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14442 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14443 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14444 | tmp_stack_push(&tf, &saved_arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14446 | append_call_frame_cfunc(v7, this_object, cfunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14448 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14449 | * prepare cfunction environment |
Marko Mikulicic |
0:c0ecb8bf28eb | 14450 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14451 | v7->inhibit_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14452 | v7->vals.arguments = args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14453 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14454 | /* call C function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14455 | rcode = cfunc(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14456 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14457 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14458 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14460 | if (is_constructor && !v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14461 | /* constructor returned non-object: replace it with `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14462 | *res = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14463 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14465 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14466 | v7->vals.arguments = saved_arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14467 | v7->inhibit_gc = saved_inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14469 | unwind_stack_1level(v7, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14471 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14472 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14473 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14475 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14476 | * Evaluate `OP_TRY_PUSH_CATCH` or `OP_TRY_PUSH_FINALLY`: Take an offset (from |
Marko Mikulicic |
0:c0ecb8bf28eb | 14477 | * the parameter of opcode) and push it onto "try stack" |
Marko Mikulicic |
0:c0ecb8bf28eb | 14478 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14479 | static void eval_try_push(struct v7 *v7, enum opcode op, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14480 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14481 | val_t arr = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14482 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14483 | bcode_off_t target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14484 | int64_t offset_tag = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14486 | tmp_stack_push(&tf, &arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14488 | /* make sure "try stack" array exists */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14489 | arr = find_call_frame_private(v7)->vals.try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14490 | if (!v7_is_array(v7, arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14491 | arr = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14492 | find_call_frame_private(v7)->vals.try_stack = arr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14493 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14494 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14495 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14496 | * push the target address at the end of the "try stack" array |
Marko Mikulicic |
0:c0ecb8bf28eb | 14497 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14498 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14499 | case OP_TRY_PUSH_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14500 | offset_tag = LBLOCK_TAG_CATCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14501 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14502 | case OP_TRY_PUSH_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14503 | offset_tag = LBLOCK_TAG_FINALLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14504 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14505 | case OP_TRY_PUSH_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14506 | offset_tag = LBLOCK_TAG_LOOP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14507 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14508 | case OP_TRY_PUSH_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14509 | offset_tag = LBLOCK_TAG_SWITCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14510 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14511 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14512 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14513 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14514 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14515 | target = bcode_get_target(&r->ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14516 | v7_array_push(v7, arr, v7_mk_number(v7, LBLOCK_ITEM_CREATE(target, offset_tag, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14517 | v7->stack.len))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14519 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14520 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14521 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14522 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14523 | * Evaluate `OP_TRY_POP`: just pop latest item from "try stack", ignoring it |
Marko Mikulicic |
0:c0ecb8bf28eb | 14524 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14525 | static enum v7_err eval_try_pop(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14526 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14527 | val_t arr = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14528 | unsigned long length; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14529 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14531 | tmp_stack_push(&tf, &arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14533 | /* get "try stack" array, which must be defined and must not be emtpy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14534 | arr = find_call_frame_private(v7)->vals.try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14535 | if (!v7_is_array(v7, arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14536 | rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is not an array"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14537 | V7_TRY(V7_INTERNAL_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14538 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14540 | length = v7_array_length(v7, arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14541 | if (length == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14542 | rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is empty"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14543 | V7_TRY(V7_INTERNAL_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14544 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14546 | /* delete the latest element of this array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14547 | v7_array_del(v7, arr, length - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14548 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14549 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14550 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14551 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14552 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14553 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14554 | static void own_bcode(struct v7 *v7, struct bcode *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14555 | mbuf_append(&v7->act_bcodes, &p, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14556 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14557 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14558 | static void disown_bcode(struct v7 *v7, struct bcode *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14559 | #ifndef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 14560 | struct bcode **vp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 14561 | (struct bcode **) (v7->act_bcodes.buf + v7->act_bcodes.len - sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14563 | /* given `p` should be the last item */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14564 | assert(*vp == p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14565 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14566 | v7->act_bcodes.len -= sizeof(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14567 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14568 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14569 | /* Keeps track of last evaluated bcodes in order to improve error reporting */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14570 | static void push_bcode_history(struct v7 *v7, enum opcode op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14571 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14573 | if (op == OP_CHECK_CALL || op == OP_CALL || op == OP_NEW) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14575 | for (i = ARRAY_SIZE(v7->last_ops) - 1; i > 0; i--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14576 | v7->last_ops[i] = v7->last_ops[i - 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14577 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14578 | v7->last_ops[0] = op; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14579 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14581 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 14582 | static void reset_last_name(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14583 | v7->vals.last_name[0] = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14584 | v7->vals.last_name[1] = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14585 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14586 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 14587 | static void reset_last_name(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14588 | /* should be inlined out */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14589 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14590 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14591 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14593 | static void prop_iter_ctx_dtor(struct v7 *v7, void *ud) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14594 | struct prop_iter_ctx *ctx = (struct prop_iter_ctx *) ud; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14595 | v7_destruct_prop_iter_ctx(v7, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14596 | free(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14597 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14599 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14600 | * Evaluates given `bcode`. If `reset_line_no` is non-zero, the line number |
Marko Mikulicic |
0:c0ecb8bf28eb | 14601 | * is initially reset to 1; otherwise, it is inherited from the previous call |
Marko Mikulicic |
0:c0ecb8bf28eb | 14602 | * frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14603 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14604 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 14605 | V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14606 | val_t this_object, uint8_t reset_line_no, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14607 | val_t *_res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14608 | struct bcode_registers r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14609 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14610 | struct v7_call_frame_base *saved_bottom_call_frame = v7->bottom_call_frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14612 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14613 | * Dummy variable just to enforce that `BTRY()` macro is used only inside the |
Marko Mikulicic |
0:c0ecb8bf28eb | 14614 | * `eval_bcode()` function |
Marko Mikulicic |
0:c0ecb8bf28eb | 14615 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14616 | uint8_t _you_should_use_BTRY_in_eval_bcode_only = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14618 | char buf[512]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14620 | val_t res = V7_UNDEFINED, v1 = V7_UNDEFINED, v2 = V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14621 | v3 = V7_UNDEFINED, v4 = V7_UNDEFINED, scope_frame = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14622 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14624 | append_call_frame_bcode(v7, NULL, bcode, this_object, get_scope(v7), 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14626 | if (reset_line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14627 | v7->call_stack->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14628 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14630 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14631 | * Set current call stack as the "bottom" call stack, so that bcode evaluator |
Marko Mikulicic |
0:c0ecb8bf28eb | 14632 | * will exit when it reaches this "bottom" |
Marko Mikulicic |
0:c0ecb8bf28eb | 14633 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14634 | v7->bottom_call_frame = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14635 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14636 | bcode_restore_registers(v7, bcode, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14638 | tmp_stack_push(&tf, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14639 | tmp_stack_push(&tf, &v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14640 | tmp_stack_push(&tf, &v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14641 | tmp_stack_push(&tf, &v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14642 | tmp_stack_push(&tf, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14643 | tmp_stack_push(&tf, &scope_frame); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14645 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14646 | * populate local variables on current scope, making them undeletable |
Marko Mikulicic |
0:c0ecb8bf28eb | 14647 | * (since they're defined with `var`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14648 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14649 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14650 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14651 | for (i = 0; i < bcode->names_cnt; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14652 | r.ops = bcode_next_name_v(v7, bcode, r.ops, &v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14654 | /* set undeletable property on current scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14655 | V7_TRY(def_property_v(v7, get_scope(v7), v1, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14656 | V7_UNDEFINED, 1 /*as_assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14657 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14658 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14659 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14660 | restart: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14661 | while (r.ops < r.end && rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14662 | enum opcode op = (enum opcode) * r.ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14664 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 14665 | if ((uint8_t) op >= _OP_LINE_NO) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14666 | unsigned char buf[sizeof(size_t)]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14667 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14668 | size_t max_llen = sizeof(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14670 | /* ASAN doesn't like out of bound reads */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14671 | if (r.ops + max_llen > r.end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14672 | max_llen = r.end - r.ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14673 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14675 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14676 | * before we decode varint, we'll have to swap MSB and LSB, but we can't |
Marko Mikulicic |
0:c0ecb8bf28eb | 14677 | * do it in place since we're decoding from constant memory, so, we also |
Marko Mikulicic |
0:c0ecb8bf28eb | 14678 | * have to copy the data to the temp buffer first. 4 bytes should be |
Marko Mikulicic |
0:c0ecb8bf28eb | 14679 | * enough for everyone's line number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14680 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14681 | memcpy(buf, r.ops, max_llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14682 | buf[0] = msb_lsb_swap(buf[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14683 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14684 | v7->call_stack->line_no = decode_varint(buf, &len) >> 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14685 | assert((size_t) len <= sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14686 | r.ops += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14687 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14688 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14689 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14690 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14692 | push_bcode_history(v7, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14694 | if (v7->need_gc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14695 | if (maybe_gc(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14696 | v7->need_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14697 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14698 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14700 | r.need_inc_ops = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14701 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14702 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14703 | char *dops = r.ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14704 | fprintf(stderr, "eval "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14705 | dump_op(v7, stderr, r.bcode, &dops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14706 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14707 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14708 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14709 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14710 | case OP_DROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14711 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14712 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14713 | case OP_DUP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14714 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14715 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14716 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14717 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14718 | case OP_2DUP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14719 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14720 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14721 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14722 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14723 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14724 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14725 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14726 | case OP_SWAP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14727 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14728 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14729 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14730 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14731 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14732 | case OP_STASH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14733 | assert(!v7->is_stashed); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14734 | v7->vals.stash = TOS(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14735 | v7->is_stashed = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14736 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14737 | case OP_UNSTASH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14738 | assert(v7->is_stashed); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14739 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14740 | PUSH(v7->vals.stash); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14741 | v7->vals.stash = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14742 | v7->is_stashed = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14743 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14745 | case OP_SWAP_DROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14746 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14747 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14748 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14749 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14751 | case OP_PUSH_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14752 | PUSH(V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14753 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14754 | case OP_PUSH_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14755 | PUSH(V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14756 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14757 | case OP_PUSH_THIS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14758 | PUSH(v7_get_this(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14759 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14760 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14761 | case OP_PUSH_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14762 | PUSH(v7_mk_boolean(v7, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14763 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14764 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14765 | case OP_PUSH_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14766 | PUSH(v7_mk_boolean(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14767 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14768 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14769 | case OP_PUSH_ZERO: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14770 | PUSH(v7_mk_number(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14771 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14772 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14773 | case OP_PUSH_ONE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14774 | PUSH(v7_mk_number(v7, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14775 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14776 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14777 | case OP_PUSH_LIT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14778 | PUSH(bcode_decode_lit(v7, r.bcode, &r.ops)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14779 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 14780 | /* name tracking */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14781 | if (!v7_is_string(TOS())) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14782 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14783 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14784 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14785 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14786 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14787 | case OP_LOGICAL_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14788 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14789 | PUSH(v7_mk_boolean(v7, !v7_is_truthy(v7, v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14790 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14791 | case OP_NOT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14792 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14793 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14794 | PUSH(v7_mk_number(v7, ~(int32_t) v7_get_double(v7, v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14795 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14796 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14797 | case OP_NEG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14798 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14799 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14800 | PUSH(v7_mk_number(v7, -v7_get_double(v7, v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14801 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14803 | case OP_POS: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14804 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14805 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14806 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14807 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14808 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14809 | case OP_ADD: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14810 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14811 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14813 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14814 | * If either operand is an object, convert both of them to primitives |
Marko Mikulicic |
0:c0ecb8bf28eb | 14815 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14816 | if (v7_is_object(v1) || v7_is_object(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14817 | BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_AUTO, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14818 | BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_AUTO, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14819 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14821 | if (v7_is_string(v1) || v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14822 | /* Convert both operands to strings, and concatenate */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14824 | BTRY(primitive_to_str(v7, v1, &v1, NULL, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14825 | BTRY(primitive_to_str(v7, v2, &v2, NULL, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14827 | PUSH(s_concat(v7, v1, v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14828 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14829 | /* Convert both operands to numbers, and sum */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14831 | BTRY(primitive_to_number(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14832 | BTRY(primitive_to_number(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14834 | PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14835 | v7_get_double(v7, v2)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14836 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14837 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14838 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14839 | case OP_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14840 | case OP_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14841 | case OP_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14842 | case OP_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14843 | case OP_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14844 | case OP_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14845 | case OP_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14846 | case OP_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14847 | case OP_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14848 | case OP_AND: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14849 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14850 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14852 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14853 | BTRY(to_number_v(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14855 | PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14856 | v7_get_double(v7, v2)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14857 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14859 | case OP_EQ_EQ: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14860 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14861 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14862 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14863 | res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14864 | } else if (v1 == v2 && v1 == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14865 | res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14866 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14867 | res = v7_mk_boolean(v7, v1 == v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14868 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14869 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14870 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14871 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14872 | case OP_NE_NE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14873 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14874 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14875 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14876 | res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) != 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14877 | } else if (v1 == v2 && v1 == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14878 | res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14879 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14880 | res = v7_mk_boolean(v7, v1 != v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14881 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14882 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14883 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14884 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14885 | case OP_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14886 | case OP_NE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14887 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14888 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14889 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14890 | * TODO(dfrank) : it's not really correct. Fix it accordingly to |
Marko Mikulicic |
0:c0ecb8bf28eb | 14891 | * the p. 4.9 of The Definitive Guide (page 71) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14892 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14893 | if (((v7_is_object(v1) || v7_is_object(v2)) && v1 == v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14894 | res = v7_mk_boolean(v7, op == OP_EQ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14895 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14896 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14897 | } else if (v7_is_undefined(v1) || v7_is_null(v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14898 | res = v7_mk_boolean( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14899 | v7, (op != OP_EQ) ^ (v7_is_undefined(v2) || v7_is_null(v2))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14900 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14901 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14902 | } else if (v7_is_undefined(v2) || v7_is_null(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14903 | res = v7_mk_boolean( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14904 | v7, (op != OP_EQ) ^ (v7_is_undefined(v1) || v7_is_null(v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14905 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14906 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14907 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14909 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14910 | int cmp = s_cmp(v7, v1, v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14911 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14912 | case OP_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14913 | res = v7_mk_boolean(v7, cmp == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14914 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14915 | case OP_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14916 | res = v7_mk_boolean(v7, cmp != 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14917 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14918 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14919 | /* should never be here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14920 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14921 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14922 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14923 | /* Convert both operands to numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14925 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14926 | BTRY(to_number_v(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14928 | res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14929 | v7_get_double(v7, v2))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14930 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14931 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14932 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14933 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14934 | case OP_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14935 | case OP_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14936 | case OP_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14937 | case OP_GE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14938 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14939 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14940 | BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_NUMBER, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14941 | BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_NUMBER, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14943 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14944 | int cmp = s_cmp(v7, v1, v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14945 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14946 | case OP_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14947 | res = v7_mk_boolean(v7, cmp < 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14948 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14949 | case OP_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14950 | res = v7_mk_boolean(v7, cmp <= 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14951 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14952 | case OP_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14953 | res = v7_mk_boolean(v7, cmp > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14954 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14955 | case OP_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14956 | res = v7_mk_boolean(v7, cmp >= 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14957 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14958 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14959 | /* should never be here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14960 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14961 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14962 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14963 | /* Convert both operands to numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14964 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14965 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14966 | BTRY(to_number_v(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14968 | res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14969 | v7_get_double(v7, v2))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14970 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14971 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14972 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14973 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14974 | case OP_INSTANCEOF: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14975 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14976 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14977 | if (!v7_is_callable(v7, v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14978 | BTRY(v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14979 | "Expecting a function in instanceof check")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14980 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14981 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14982 | PUSH(v7_mk_boolean( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14983 | v7, is_prototype_of(v7, v1, v7_get(v7, v2, "prototype", 9)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14984 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14985 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14986 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14987 | case OP_TYPEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14988 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14989 | switch (val_type(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14990 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14991 | res = v7_mk_string(v7, "number", 6, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14992 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14993 | case V7_TYPE_STRING: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14994 | res = v7_mk_string(v7, "string", 6, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14995 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14996 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14997 | res = v7_mk_string(v7, "boolean", 7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14998 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14999 | case V7_TYPE_FUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15000 | case V7_TYPE_CFUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15001 | case V7_TYPE_CFUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15002 | res = v7_mk_string(v7, "function", 8, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15003 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15004 | case V7_TYPE_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15005 | res = v7_mk_string(v7, "undefined", 9, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15006 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15007 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15008 | res = v7_mk_string(v7, "object", 6, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15009 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15010 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15011 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15012 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15013 | case OP_IN: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15014 | struct v7_property *prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15015 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15016 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15017 | BTRY(to_string(v7, v1, NULL, buf, sizeof(buf), NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15018 | prop = v7_get_property(v7, v2, buf, ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15019 | PUSH(v7_mk_boolean(v7, prop != NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15020 | } break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15021 | case OP_GET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15022 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15023 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15024 | BTRY(v7_get_throwing_v(v7, v1, v2, &v3)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15025 | PUSH(v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15026 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15027 | v7->vals.last_name[1] = v7->vals.last_name[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15028 | v7->vals.last_name[0] = v2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15029 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15030 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15031 | case OP_SET: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15032 | v3 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15033 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15034 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15035 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15036 | /* convert name to string, if it's not already */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15037 | BTRY(to_string(v7, v2, &v2, NULL, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15039 | /* set value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15040 | BTRY(set_property_v(v7, v1, v2, v3, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15042 | PUSH(v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15043 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15044 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15045 | case OP_GET_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15046 | case OP_SAFE_GET_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15047 | struct v7_property *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15048 | assert(r.ops < r.end - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15049 | v1 = bcode_decode_lit(v7, r.bcode, &r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15050 | BTRY(v7_get_property_v(v7, get_scope(v7), v1, &p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15051 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15052 | if (op == OP_SAFE_GET_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15053 | PUSH(V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15054 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15055 | /* variable does not exist: Reference Error */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15056 | V7_TRY(bcode_throw_reference_error(v7, &r, v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15057 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15059 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15060 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15061 | BTRY(v7_property_value(v7, get_scope(v7), p, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15062 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15063 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15064 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15065 | v7->vals.last_name[0] = v1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15066 | v7->vals.last_name[1] = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15067 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15068 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15069 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15070 | case OP_SET_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15071 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15072 | v3 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15073 | v2 = bcode_decode_lit(v7, r.bcode, &r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15074 | v1 = get_scope(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15076 | BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15077 | prop = v7_get_property(v7, v1, buf, strlen(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15078 | if (prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15079 | /* Property already exists: update its value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15080 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15081 | * TODO(dfrank): currently we can't use `def_property_v()` here, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15082 | * because if the property was already found somewhere in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 15083 | * prototype chain, then it should be updated, instead of creating a |
Marko Mikulicic |
0:c0ecb8bf28eb | 15084 | * new one on the top of the scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15085 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15086 | * Probably we need to make `def_property_v()` more generic and |
Marko Mikulicic |
0:c0ecb8bf28eb | 15087 | * use it here; or split `def_property_v()` into smaller pieces and |
Marko Mikulicic |
0:c0ecb8bf28eb | 15088 | * use one of them here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15089 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15090 | if (!(prop->attributes & V7_PROPERTY_NON_WRITABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15091 | prop->value = v3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15093 | } else if (!r.bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15094 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15095 | * Property does not exist: since we're not in strict mode, let's |
Marko Mikulicic |
0:c0ecb8bf28eb | 15096 | * create new property at Global Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15097 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15098 | BTRY(set_property_v(v7, v7_get_global(v7), v2, v3, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15099 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15100 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15101 | * In strict mode, throw reference error instead of polluting Global |
Marko Mikulicic |
0:c0ecb8bf28eb | 15102 | * Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15103 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15104 | V7_TRY(bcode_throw_reference_error(v7, &r, v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15105 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15106 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15107 | PUSH(v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15108 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15109 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15110 | case OP_JMP: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15111 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15112 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15113 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15114 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15115 | case OP_JMP_FALSE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15116 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15117 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15118 | if (!v7_is_truthy(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15119 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15120 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15121 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15122 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15123 | case OP_JMP_TRUE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15124 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15125 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15126 | if (v7_is_truthy(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15127 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15128 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15129 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15130 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15131 | case OP_JMP_TRUE_DROP: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15132 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15133 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15134 | if (v7_is_truthy(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15135 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15136 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15137 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15138 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15139 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15140 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15142 | case OP_JMP_IF_CONTINUE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15143 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15144 | if (v7->is_continuing) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15145 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15146 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15147 | v7->is_continuing = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15148 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15149 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15150 | case OP_CREATE_OBJ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15151 | PUSH(v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15152 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15153 | case OP_CREATE_ARR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15154 | PUSH(v7_mk_array(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15155 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15156 | case OP_PUSH_PROP_ITER_CTX: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15157 | struct prop_iter_ctx *ctx = |
Marko Mikulicic |
0:c0ecb8bf28eb | 15158 | (struct prop_iter_ctx *) calloc(1, sizeof(*ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15159 | BTRY(init_prop_iter_ctx(v7, TOS(), 1, ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15160 | v1 = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15161 | v7_set_user_data(v7, v1, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15162 | v7_set_destructor_cb(v7, v1, prop_iter_ctx_dtor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15163 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15164 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15165 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15166 | case OP_NEXT_PROP: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15167 | struct prop_iter_ctx *ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15168 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15169 | v1 = POP(); /* ctx */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15170 | v2 = POP(); /* object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15172 | ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15173 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15174 | if (v7_is_object(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15175 | v7_prop_attr_t attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15177 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15178 | /* iterate properties until we find a non-hidden enumerable one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15179 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15180 | BTRY(next_prop(v7, ctx, &res, NULL, &attrs, &ok)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15181 | } while (ok && (attrs & (_V7_PROPERTY_HIDDEN | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15182 | V7_PROPERTY_NON_ENUMERABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15183 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15184 | if (!ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15185 | /* no more properties in this object: proceed to the prototype */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15186 | v2 = v7_get_proto(v7, v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15187 | if (get_generic_object_struct(v2) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15188 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15189 | * the prototype is a generic object, so, init the context for |
Marko Mikulicic |
0:c0ecb8bf28eb | 15190 | * props iteration |
Marko Mikulicic |
0:c0ecb8bf28eb | 15191 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15192 | v7_destruct_prop_iter_ctx(v7, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15193 | BTRY(init_prop_iter_ctx(v7, v2, 1, ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15194 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15195 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15196 | * we can't iterate the prototype's props, so, just stop |
Marko Mikulicic |
0:c0ecb8bf28eb | 15197 | * iteration. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15198 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15199 | ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15202 | } while (!ok && ctx != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15203 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15204 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15205 | * Not an object: reset the context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15206 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15207 | ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15208 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15210 | if (ctx == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15211 | PUSH(v7_mk_boolean(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15213 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15214 | * We could leave the context unfreed, and let the |
Marko Mikulicic |
0:c0ecb8bf28eb | 15215 | * `prop_iter_ctx_dtor()` free it when the v1 will be GC-d, but |
Marko Mikulicic |
0:c0ecb8bf28eb | 15216 | * let's do that earlier. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15217 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15218 | ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15219 | v7_destruct_prop_iter_ctx(v7, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15220 | free(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15221 | v7_set_user_data(v7, v1, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15222 | v7_set_destructor_cb(v7, v1, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15223 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15224 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15225 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15226 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15227 | PUSH(v7_mk_boolean(v7, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15228 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15229 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15230 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15231 | case OP_FUNC_LIT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15232 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15233 | v2 = bcode_instantiate_function(v7, v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15234 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15235 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15236 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15237 | case OP_CHECK_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15238 | v1 = TOS(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15239 | if (!v7_is_callable(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15240 | int arity = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15241 | enum v7_err ignore; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15242 | /* tried to call non-function object: throw a TypeError */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15244 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15245 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15246 | * try to provide some useful context for the error message |
Marko Mikulicic |
0:c0ecb8bf28eb | 15247 | * using a good-enough heuristics |
Marko Mikulicic |
0:c0ecb8bf28eb | 15248 | * but defer actual throw when process the incriminated call |
Marko Mikulicic |
0:c0ecb8bf28eb | 15249 | * in order to evaluate the arguments as required by the spec. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15250 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15251 | if (v7->last_ops[0] == OP_GET_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15252 | arity = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15253 | } else if (v7->last_ops[0] == OP_GET && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15254 | v7->last_ops[1] == OP_PUSH_LIT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15255 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15256 | * OP_PUSH_LIT is used to both push property names for OP_GET |
Marko Mikulicic |
0:c0ecb8bf28eb | 15257 | * and for pushing actual literals. During PUSH_LIT push lit |
Marko Mikulicic |
0:c0ecb8bf28eb | 15258 | * evaluation we reset the last name variable in case the literal |
Marko Mikulicic |
0:c0ecb8bf28eb | 15259 | * is not a string, such as in `[].foo()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15260 | * Unfortunately it doesn't handle `"foo".bar()`; could be |
Marko Mikulicic |
0:c0ecb8bf28eb | 15261 | * solved by adding another bytecode for property literals but |
Marko Mikulicic |
0:c0ecb8bf28eb | 15262 | * probably it doesn't matter much. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15263 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15264 | if (v7_is_undefined(v7->vals.last_name[1])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15265 | arity = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15266 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15267 | arity = 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15268 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15270 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15272 | switch (arity) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15273 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15274 | ignore = v7_throwf(v7, TYPE_ERROR, "value is not a function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15275 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15276 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15278 | case 1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15279 | ignore = v7_throwf(v7, TYPE_ERROR, "%s is not a function", |
Marko Mikulicic |
0:c0ecb8bf28eb | 15280 | v7_get_cstring(v7, &v7->vals.last_name[0])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15281 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15282 | case 2: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15283 | ignore = v7_throwf(v7, TYPE_ERROR, "%s.%s is not a function", |
Marko Mikulicic |
0:c0ecb8bf28eb | 15284 | v7_get_cstring(v7, &v7->vals.last_name[1]), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15285 | v7_get_cstring(v7, &v7->vals.last_name[0])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15286 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15287 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15288 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15290 | v7->vals.call_check_ex = v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15291 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15292 | (void) ignore; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15293 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15294 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15295 | case OP_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15296 | case OP_NEW: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15297 | /* Naive implementation pending stack frame redesign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15298 | int args = (int) *(++r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15299 | uint8_t is_constructor = (op == OP_NEW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15300 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15301 | if (SP() < (args + 1 /*func*/ + 1 /*this*/)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15302 | BTRY(v7_throwf(v7, INTERNAL_ERROR, "stack underflow")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15303 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15304 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15305 | v2 = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15306 | while (args > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15307 | BTRY(v7_array_set_throwing(v7, v2, --args, POP(), NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15308 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15309 | /* pop function to call */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15310 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15312 | /* pop `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15313 | v3 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15315 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15316 | * adjust `this` if the function is called with the constructor |
Marko Mikulicic |
0:c0ecb8bf28eb | 15317 | * invocation pattern |
Marko Mikulicic |
0:c0ecb8bf28eb | 15318 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15319 | if (is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15320 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15321 | * The function is invoked as a constructor: we ignore `this` |
Marko Mikulicic |
0:c0ecb8bf28eb | 15322 | * value popped from stack, create new object and set prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15323 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15324 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15325 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15326 | * get "prototype" property from the constructor function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15327 | * and make sure it's an object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15328 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15329 | v4 = v7_get(v7, v1 /*func*/, "prototype", 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15330 | if (!v7_is_object(v4)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15331 | /* TODO(dfrank): box primitive value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15332 | BTRY(v7_throwf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15333 | v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15334 | "Cannot set a primitive value as object prototype")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15335 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15336 | } else if (is_cfunction_lite(v4)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15337 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15338 | * TODO(dfrank): maybe add support for a cfunction pointer to be |
Marko Mikulicic |
0:c0ecb8bf28eb | 15339 | * a prototype |
Marko Mikulicic |
0:c0ecb8bf28eb | 15340 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15341 | BTRY(v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15342 | "Not implemented: cfunction as a prototype")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15343 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15346 | /* create an object with given prototype */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15347 | v3 = mk_object(v7, v4 /*prototype*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15348 | v4 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15349 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15351 | if (!v7_is_callable(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15352 | /* tried to call non-function object: throw a TypeError */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15353 | BTRY(v7_throw(v7, v7->vals.call_check_ex)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15354 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15355 | } else if (is_cfunction_lite(v1) || is_cfunction_obj(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15356 | /* call cfunction */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15358 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15359 | * In "function invocation pattern", the `this` value popped from |
Marko Mikulicic |
0:c0ecb8bf28eb | 15360 | * stack is an `undefined`. And in non-strict mode, we should change |
Marko Mikulicic |
0:c0ecb8bf28eb | 15361 | * it to global object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15362 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15363 | if (!is_constructor && !r.bcode->strict_mode && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15364 | v7_is_undefined(v3)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15365 | v3 = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15366 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15367 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15368 | BTRY(call_cfunction(v7, v1 /*func*/, v3 /*this*/, v2 /*args*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15369 | is_constructor, &v4)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15371 | /* push value returned from C function to bcode stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15372 | PUSH(v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15374 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15375 | char *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15376 | struct v7_js_function *func = get_js_function_struct(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15378 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15379 | * In "function invocation pattern", the `this` value popped from |
Marko Mikulicic |
0:c0ecb8bf28eb | 15380 | * stack is an `undefined`. And in non-strict mode, we should change |
Marko Mikulicic |
0:c0ecb8bf28eb | 15381 | * it to global object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15382 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15383 | if (!is_constructor && !func->bcode->strict_mode && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15384 | v7_is_undefined(v3)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15385 | v3 = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15386 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15388 | scope_frame = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15390 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15391 | * Before actual opcodes, `ops` contains one or more |
Marko Mikulicic |
0:c0ecb8bf28eb | 15392 | * null-terminated strings: first of all, the function name (if the |
Marko Mikulicic |
0:c0ecb8bf28eb | 15393 | * function is anonymous, it's an empty string). |
Marko Mikulicic |
0:c0ecb8bf28eb | 15394 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15395 | * Then, argument names follow. We know number of arguments, so, we |
Marko Mikulicic |
0:c0ecb8bf28eb | 15396 | * know how many names to take. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15397 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15398 | * And then, local variable names follow. We know total number of |
Marko Mikulicic |
0:c0ecb8bf28eb | 15399 | * strings (`names_cnt`), so, again, we know how many names to |
Marko Mikulicic |
0:c0ecb8bf28eb | 15400 | * take. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15401 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15402 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15403 | ops = func->bcode->ops.p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15405 | /* populate function itself */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15406 | ops = bcode_next_name_v(v7, func->bcode, ops, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15407 | BTRY(def_property_v(v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15408 | v1, 0 /*not assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15410 | /* populate arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15411 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15412 | int arg_num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15413 | for (arg_num = 0; arg_num < func->bcode->args_cnt; ++arg_num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15414 | ops = bcode_next_name_v(v7, func->bcode, ops, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15415 | BTRY(def_property_v( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15416 | v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15417 | v7_array_get(v7, v2, arg_num), 0 /*not assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15418 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15419 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15421 | /* populate `arguments` object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15422 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15423 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15424 | * TODO(dfrank): it's actually much more complicated than that: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15425 | * it's not an array, it's an array-like object. More, in |
Marko Mikulicic |
0:c0ecb8bf28eb | 15426 | * non-strict mode, elements of `arguments` object are just aliases |
Marko Mikulicic |
0:c0ecb8bf28eb | 15427 | * for actual arguments, so this one: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15428 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15429 | * `(function(a){arguments[0]=2; return a;})(1);` |
Marko Mikulicic |
0:c0ecb8bf28eb | 15430 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15431 | * should yield 2. Currently, it yields 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15432 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15433 | v7_def(v7, scope_frame, "arguments", 9, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15434 | v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15436 | /* populate local variables */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15437 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15438 | uint8_t loc_num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15439 | uint8_t loc_cnt = func->bcode->names_cnt - func->bcode->args_cnt - |
Marko Mikulicic |
0:c0ecb8bf28eb | 15440 | 1 /*func name*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15441 | for (loc_num = 0; loc_num < loc_cnt; ++loc_num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15442 | ops = bcode_next_name_v(v7, func->bcode, ops, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15443 | BTRY(def_property_v(v7, scope_frame, v4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15444 | V7_DESC_CONFIGURABLE(0), V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15445 | 0 /*not assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15447 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15449 | /* transfer control to the function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15450 | V7_TRY(bcode_perform_call(v7, scope_frame, func, &r, v3 /*this*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15451 | ops, is_constructor)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15453 | scope_frame = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15454 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15455 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15456 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15457 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15458 | case OP_RET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15459 | bcode_adjust_retval(v7, 1 /*explicit return*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15460 | V7_TRY(bcode_perform_return(v7, &r, 1 /*take value from stack*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15461 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15462 | case OP_DELETE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15463 | case OP_DELETE_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15464 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15465 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15467 | res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15469 | /* pop property name to delete */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15470 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15472 | if (op == OP_DELETE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15473 | /* pop object to delete the property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15474 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15475 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15476 | /* use scope as an object to delete the property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15477 | v1 = get_scope(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15478 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15480 | if (!v7_is_object(v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15481 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15482 | * the "object" to delete a property from is not actually an object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15483 | * (at least this can happen with cfunction pointers), will just |
Marko Mikulicic |
0:c0ecb8bf28eb | 15484 | * return `true` |
Marko Mikulicic |
0:c0ecb8bf28eb | 15485 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15486 | goto delete_clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15489 | BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), &name_len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15491 | prop = v7_get_property(v7, v1, buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15492 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15493 | /* not found a property; will just return `true` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15494 | goto delete_clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15495 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15496 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15497 | /* found needed property */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15499 | if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15500 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15501 | * this property is undeletable. In non-strict mode, we just |
Marko Mikulicic |
0:c0ecb8bf28eb | 15502 | * return `false`; otherwise, we throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15503 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15504 | if (!r.bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15505 | res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15506 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15507 | BTRY(v7_throwf(v7, TYPE_ERROR, "Cannot delete property '%s'", buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15508 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15509 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15510 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15511 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15512 | * delete property: when we operate on the current scope, we should |
Marko Mikulicic |
0:c0ecb8bf28eb | 15513 | * walk the prototype chain when deleting property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15514 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15515 | * But when we operate on a "real" object, we should delete own |
Marko Mikulicic |
0:c0ecb8bf28eb | 15516 | * properties only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15517 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15518 | if (op == OP_DELETE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15519 | v7_del(v7, v1, buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15520 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15521 | del_property_deep(v7, v1, buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15522 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15525 | delete_clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15526 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15527 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15528 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15529 | case OP_TRY_PUSH_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15530 | case OP_TRY_PUSH_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15531 | case OP_TRY_PUSH_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15532 | case OP_TRY_PUSH_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15533 | eval_try_push(v7, op, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15534 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15535 | case OP_TRY_POP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15536 | V7_TRY(eval_try_pop(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15537 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15538 | case OP_AFTER_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15539 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15540 | * exited from `finally` block: if some value is currently being |
Marko Mikulicic |
0:c0ecb8bf28eb | 15541 | * returned, continue returning it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15542 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15543 | * Likewise, if some value is currently being thrown, continue |
Marko Mikulicic |
0:c0ecb8bf28eb | 15544 | * unwinding stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15545 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15546 | if (v7->is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15547 | V7_TRY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15548 | bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15549 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15550 | } else if (v7->is_returned) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15551 | V7_TRY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15552 | bcode_perform_return(v7, &r, 0 /*don't take value from stack*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15553 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15554 | } else if (v7->is_breaking) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15555 | bcode_perform_break(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15556 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15557 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15558 | case OP_THROW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15559 | V7_TRY(bcode_perform_throw(v7, &r, 1 /*take thrown value*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15560 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15561 | case OP_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15562 | bcode_perform_break(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15563 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15564 | case OP_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15565 | v7->is_continuing = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15566 | bcode_perform_break(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15567 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15568 | case OP_ENTER_CATCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15569 | /* pop thrown value from stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15570 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15571 | /* get the name of the thrown value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15572 | v2 = bcode_decode_lit(v7, r.bcode, &r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15574 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15575 | * create a new stack frame (a "private" one), and set exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 15576 | * property on it |
Marko Mikulicic |
0:c0ecb8bf28eb | 15577 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15578 | scope_frame = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15579 | BTRY(set_property_v(v7, scope_frame, v2, v1, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15581 | /* Push this "private" frame on the call stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15582 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15583 | /* new scope_frame will inherit from the current scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15584 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15585 | obj_prototype_set(v7, get_object_struct(scope_frame), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15586 | get_object_struct(get_scope(v7))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15587 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15588 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15589 | * Create new `call_frame` which will replace `v7->call_stack`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15590 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15591 | append_call_frame_private(v7, scope_frame); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15593 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15594 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15595 | case OP_EXIT_CATCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15596 | v7_call_frame_mask_t frame_type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15597 | /* unwind 1 frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15598 | frame_type_mask = unwind_stack_1level(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15599 | /* make sure the unwound frame is a "private" frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15600 | assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15601 | #if defined(NDEBUG) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15602 | (void) frame_type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15603 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15604 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15605 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15606 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15607 | BTRY(v7_throwf(v7, INTERNAL_ERROR, "Unknown opcode: %d", (int) op)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15608 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15609 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15611 | op_done: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15612 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15613 | /* print current stack state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15614 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15615 | char buf[40]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15616 | char *str = v7_stringify(v7, TOS(), buf, sizeof(buf), V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15617 | fprintf(stderr, " stack size: %u, TOS: '%s'\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 15618 | (unsigned int) (v7->stack.len / sizeof(val_t)), str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15619 | if (str != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15620 | free(str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15621 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15623 | #ifdef V7_BCODE_TRACE_STACK |
Marko Mikulicic |
0:c0ecb8bf28eb | 15624 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15625 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15626 | for (i = 0; i < (v7->stack.len / sizeof(val_t)); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15627 | char *str = v7_stringify(v7, stack_at(&v7->stack, i), buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15628 | sizeof(buf), V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15630 | fprintf(stderr, " #: '%s'\n", str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15632 | if (str != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15633 | free(str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15634 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15636 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15637 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15638 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15639 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15640 | if (r.need_inc_ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15641 | r.ops++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15642 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15643 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15645 | /* implicit return */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15646 | if (v7->call_stack != v7->bottom_call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15647 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15648 | fprintf(stderr, "return implicitly\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15649 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15650 | bcode_adjust_retval(v7, 0 /*implicit return*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15651 | V7_TRY(bcode_perform_return(v7, &r, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15652 | goto restart; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15653 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15654 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15655 | const char *s = (get_scope(v7) != v7->vals.global_object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15656 | ? "not global object" |
Marko Mikulicic |
0:c0ecb8bf28eb | 15657 | : "global object"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15658 | fprintf(stderr, "reached bottom_call_frame (%s)\n", s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15659 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15660 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15661 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15662 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15664 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15665 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15666 | * bcode evaluated successfully. Make sure try stack is empty. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15667 | * (data stack will be checked below, in `clean`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15668 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15669 | #ifndef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 15670 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15671 | unsigned long try_stack_len = |
Marko Mikulicic |
0:c0ecb8bf28eb | 15672 | v7_array_length(v7, find_call_frame_private(v7)->vals.try_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15673 | if (try_stack_len != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15674 | fprintf(stderr, "try_stack_len=%lu, should be 0\n", try_stack_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15675 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15676 | assert(try_stack_len == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15678 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15680 | /* get the value returned from the evaluated script */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15681 | *_res = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15682 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15683 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15684 | assert(v7->bottom_call_frame == v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15685 | unwind_stack_1level(v7, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15687 | v7->bottom_call_frame = saved_bottom_call_frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15689 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15690 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15691 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15693 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15694 | * TODO(dfrank) this function is probably too overloaded: it handles both |
Marko Mikulicic |
0:c0ecb8bf28eb | 15695 | * `v7_exec` and `v7_apply`. Read below why it's written this way, but it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 15696 | * probably a good idea to factor out common functionality in some other |
Marko Mikulicic |
0:c0ecb8bf28eb | 15697 | * function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15698 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15699 | * If `src` is not `NULL`, then we behave in favour of `v7_exec`: parse, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15700 | * compile, and evaluate the script. The `func` and `args` are ignored. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15701 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15702 | * If, however, `src` is `NULL`, then we behave in favour of `v7_apply`: we |
Marko Mikulicic |
0:c0ecb8bf28eb | 15703 | * call the provided `func` with `args`. But unlike interpreter, we can't just |
Marko Mikulicic |
0:c0ecb8bf28eb | 15704 | * call the provided function: we need to setup environment for this call. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15705 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15706 | * Currently, we just quickly generate the "wrapper" bcode for the function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15707 | * This wrapper bcode looks like this: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15708 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15709 | * OP_PUSH_UNDEFINED |
Marko Mikulicic |
0:c0ecb8bf28eb | 15710 | * OP_PUSH_LIT # push this |
Marko Mikulicic |
0:c0ecb8bf28eb | 15711 | * OP_PUSH_LIT # push function |
Marko Mikulicic |
0:c0ecb8bf28eb | 15712 | * OP_PUSH_LIT # push arg1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 15713 | * OP_PUSH_LIT # push arg2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 15714 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 15715 | * OP_PUSH_LIT # push argN |
Marko Mikulicic |
0:c0ecb8bf28eb | 15716 | * OP_CALL(N) # call function with N arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 15717 | * OP_SWAP_DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 15718 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15719 | * and then, bcode evaluator proceeds with this code. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15720 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15721 | * In fact, both cases (eval or apply) are quite similar: we should prepare |
Marko Mikulicic |
0:c0ecb8bf28eb | 15722 | * environment for the bcode evaluation in exactly the same way, and the only |
Marko Mikulicic |
0:c0ecb8bf28eb | 15723 | * different part is where we get the bcode from. This is why that |
Marko Mikulicic |
0:c0ecb8bf28eb | 15724 | * functionality is baked in the single function, but it would be good to make |
Marko Mikulicic |
0:c0ecb8bf28eb | 15725 | * it suck less. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15726 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15727 | V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15728 | const char *filename, val_t func, val_t args, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15729 | val_t this_object, int is_json, int fr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15730 | uint8_t is_constructor, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15731 | #if defined(V7_BCODE_TRACE_SRC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15732 | fprintf(stderr, "src:'%s'\n", src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15733 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15735 | /* TODO(mkm): use GC pool */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15736 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15737 | struct ast *a = (struct ast *) malloc(sizeof(struct ast)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15738 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15739 | size_t saved_stack_len = v7->stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15740 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15741 | val_t _res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15742 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15743 | struct bcode *bcode = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15744 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15745 | struct stack_track_ctx stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15746 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15747 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15748 | unsigned noopt : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15749 | unsigned line_no_reset : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15750 | } flags = {0, 0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15751 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15752 | (void) filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15754 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15755 | v7_stack_track_start(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15756 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15758 | tmp_stack_push(&tf, &func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15759 | tmp_stack_push(&tf, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15760 | tmp_stack_push(&tf, &this_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15761 | tmp_stack_push(&tf, &_res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15762 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15763 | /* init new bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15764 | bcode = (struct bcode *) calloc(1, sizeof(*bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15765 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15766 | bcode_init(bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15767 | #ifndef V7_FORCE_STRICT_MODE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15768 | 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15769 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 15770 | 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15771 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15772 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 15773 | filename ? shdata_create_from_string(filename) : NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15774 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 15775 | NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15776 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15777 | 0 /*filename not in ROM*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15778 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15780 | retain_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15781 | own_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15783 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15784 | ast_init(a, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15785 | a->refcnt = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15786 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15787 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15788 | if (src != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15789 | /* Caller provided some source code, so, handle it somehow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15790 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15791 | flags.line_no_reset = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15793 | if (src_len >= sizeof(BIN_BCODE_SIGNATURE) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15794 | strncmp(BIN_BCODE_SIGNATURE, src, sizeof(BIN_BCODE_SIGNATURE)) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15795 | /* we have a serialized bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15797 | bcode_deserialize(v7, bcode, src + sizeof(BIN_BCODE_SIGNATURE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15799 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15800 | * Currently, we only support serialized bcode that is stored in some |
Marko Mikulicic |
0:c0ecb8bf28eb | 15801 | * mmapped memory. Otherwise, we don't yet have any mechanism to free |
Marko Mikulicic |
0:c0ecb8bf28eb | 15802 | * this memory at the appropriate time. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15803 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15804 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15805 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15806 | * TODO(dfrank): currently, we remove this assert, and introduce memory |
Marko Mikulicic |
0:c0ecb8bf28eb | 15807 | * leak. We need to support that properly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15808 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15809 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 15810 | assert(fr == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15811 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 15812 | if (fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15813 | fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15815 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15816 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15817 | /* Maybe regular JavaScript source or binary AST data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15818 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15820 | if (src_len >= sizeof(BIN_AST_SIGNATURE) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15821 | strncmp(BIN_AST_SIGNATURE, src, sizeof(BIN_AST_SIGNATURE)) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15822 | /* we have binary AST data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15824 | if (fr == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15825 | /* Unmanaged memory, usually rom or mmapped flash */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15826 | mbuf_free(&a->mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15827 | a->mbuf.buf = (char *) (src + sizeof(BIN_AST_SIGNATURE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15828 | a->mbuf.size = a->mbuf.len = src_len - sizeof(BIN_AST_SIGNATURE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15829 | a->refcnt++; /* prevent freeing */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15830 | flags.noopt = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15831 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15832 | mbuf_append(&a->mbuf, src + sizeof(BIN_AST_SIGNATURE), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15833 | src_len - sizeof(BIN_AST_SIGNATURE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15834 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15835 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15836 | /* we have regular JavaScript source, so, parse it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15837 | V7_TRY(parse(v7, a, src, src_len, is_json)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15838 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15840 | /* we now have binary AST, let's compile it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15842 | if (!flags.noopt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15843 | ast_optimize(a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15845 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 15846 | v7->function_arena_ast_size += a->mbuf.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15847 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15849 | if (v7_is_undefined(this_object)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15850 | this_object = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15851 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15853 | if (!is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15854 | V7_TRY(compile_script(v7, a, bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15855 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15856 | ast_off_t pos = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15857 | V7_TRY(compile_expr(v7, a, &pos, bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15859 | #else /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15860 | (void) is_json; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15861 | /* Parsing JavaScript code is disabled */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15862 | rcode = v7_throwf(v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15863 | "Parsing JS code is disabled by V7_NO_COMPILER"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15864 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15865 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15868 | } else if (is_js_function(func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15869 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15870 | * Caller did not provide source code, so, assume we should call |
Marko Mikulicic |
0:c0ecb8bf28eb | 15871 | * provided function. Here, we prepare "wrapper" bcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15872 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15874 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15875 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15876 | int args_cnt = v7_array_length(v7, args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15878 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15880 | bcode_op(&bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15882 | /* push `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15883 | lit = bcode_add_lit(&bbuilder, this_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15884 | bcode_push_lit(&bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15886 | /* push func literal */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15887 | lit = bcode_add_lit(&bbuilder, func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15888 | bcode_push_lit(&bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15890 | /* push args */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15891 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15892 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15893 | for (i = 0; i < args_cnt; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15894 | lit = bcode_add_lit(&bbuilder, v7_array_get(v7, args, i)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15895 | bcode_push_lit(&bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15897 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15899 | bcode_op(&bbuilder, OP_CALL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15900 | /* TODO(dfrank): check if args <= 0x7f */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15901 | bcode_op(&bbuilder, (uint8_t) args_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15903 | bcode_op(&bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15905 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15906 | } else if (is_cfunction_lite(func) || is_cfunction_obj(v7, func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15907 | /* call cfunction */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15909 | V7_TRY(call_cfunction(v7, func, this_object, args, is_constructor, &_res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15911 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15912 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15913 | /* value is not a function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15914 | V7_TRY(v7_throwf(v7, TYPE_ERROR, "value is not a function")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15917 | /* We now have bcode to evaluate; proceed to it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15918 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15919 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15920 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15921 | * Before we evaluate bcode, we can safely release AST since it's not needed |
Marko Mikulicic |
0:c0ecb8bf28eb | 15922 | * anymore. Note that there's no leak here: if we `goto clean` from somewhere |
Marko Mikulicic |
0:c0ecb8bf28eb | 15923 | * above, we'll anyway release the AST under `clean` as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15924 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15925 | release_ast(v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15926 | a = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15927 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15929 | /* Evaluate bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15930 | V7_TRY(eval_bcode(v7, bcode, this_object, flags.line_no_reset, &_res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15931 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15932 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15934 | /* free `src` if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15935 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15936 | * TODO(dfrank) : free it above, just after parsing, and make sure you use |
Marko Mikulicic |
0:c0ecb8bf28eb | 15937 | * V7_TRY2() with custom label instead of V7_TRY() |
Marko Mikulicic |
0:c0ecb8bf28eb | 15938 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15939 | if (src != NULL && fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15940 | free((void *) src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15943 | /* disown and release current bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15944 | disown_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15945 | release_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15946 | bcode = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15948 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15949 | /* some exception happened. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15950 | _res = v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15952 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15953 | * if this is a top-level bcode, clear thrown error from the v7 context |
Marko Mikulicic |
0:c0ecb8bf28eb | 15954 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15955 | * TODO(dfrank): do we really need to do this? |
Marko Mikulicic |
0:c0ecb8bf28eb | 15956 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15957 | * If we don't clear the error, then we should clear it manually after each |
Marko Mikulicic |
0:c0ecb8bf28eb | 15958 | * call to v7_exec() or friends; otherwise, all the following calls will |
Marko Mikulicic |
0:c0ecb8bf28eb | 15959 | * see this error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15960 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15961 | * On the other hand, user would still need to clear the error if he calls |
Marko Mikulicic |
0:c0ecb8bf28eb | 15962 | * v7_exec() from some cfunction. So, currently, sometimes we don't need |
Marko Mikulicic |
0:c0ecb8bf28eb | 15963 | * to clear the error, and sometimes we do, which is confusing. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15964 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15965 | if (v7->act_bcodes.len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15966 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15967 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15968 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15971 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15972 | * Data stack should have the same length as it was before evaluating script. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15973 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15974 | if (v7->stack.len != saved_stack_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15975 | fprintf(stderr, "len=%d, saved=%d\n", (int) v7->stack.len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15976 | (int) saved_stack_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15977 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15978 | assert(v7->stack.len == saved_stack_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15980 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15981 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15982 | * release AST if needed (normally, it's already released above, before |
Marko Mikulicic |
0:c0ecb8bf28eb | 15983 | * bcode evaluation) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15984 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15985 | if (a != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15986 | release_ast(v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15987 | a = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15988 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15989 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15991 | if (is_constructor && !v7_is_object(_res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15992 | /* constructor returned non-object: replace it with `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15993 | _res = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15994 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15996 | /* Provide the caller with the result, if asked to do so */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15997 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15998 | *res = _res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15999 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16000 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16001 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16002 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16003 | int diff = v7_stack_track_end(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16004 | if (diff > v7->stack_stat[V7_STACK_STAT_EXEC]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16005 | v7->stack_stat[V7_STACK_STAT_EXEC] = diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16008 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16010 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16011 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16012 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16014 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 16015 | V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16016 | v7_val_t args, uint8_t is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16017 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16018 | return b_exec(v7, NULL, 0, NULL, func, args, this_obj, 0, 0, is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16019 | res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16020 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16021 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16022 | #line 1 "v7/src/core.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16023 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16024 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16025 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16026 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16027 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16029 | /* Amalgamated: #include "v7/builtin/builtin.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16030 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16031 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16032 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16033 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16034 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16035 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16036 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16037 | /* Amalgamated: #include "v7/src/stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16038 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16039 | /* Amalgamated: #include "v7/src/heapusage.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16040 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16042 | #ifdef V7_THAW |
Marko Mikulicic |
0:c0ecb8bf28eb | 16043 | extern struct v7_vals *fr_vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16044 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16046 | #ifdef HAS_V7_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 16047 | double _v7_infinity; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16048 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16050 | #ifdef HAS_V7_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 16051 | double _v7_nan; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16052 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16054 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16055 | struct v7 *v7_head = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16056 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16058 | static void generic_object_destructor(struct v7 *v7, void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16059 | struct v7_generic_object *o = (struct v7_generic_object *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16060 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16061 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16063 | /* TODO(mkm): make regexp use user data API */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16064 | p = v7_get_own_property2(v7, v7_object_to_value(&o->base), "", 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16065 | _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16066 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16067 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 16068 | if (p != NULL && (p->value & V7_TAG_MASK) == V7_TAG_REGEXP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16069 | struct v7_regexp *rp = (struct v7_regexp *) get_ptr(p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16070 | v7_disown(v7, &rp->regexp_string); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16071 | slre_free(rp->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16072 | free(rp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16073 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16074 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16076 | if (o->base.attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16077 | if (p != NULL && |
Marko Mikulicic |
0:c0ecb8bf28eb | 16078 | ((abuf = (struct mbuf *) v7_get_ptr(v7, p->value)) != NULL)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16079 | mbuf_free(abuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16080 | free(abuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16082 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16084 | if (o->base.attributes & V7_OBJ_HAS_DESTRUCTOR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16085 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16086 | for (p = o->base.properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16087 | if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16088 | if (v7_is_foreign(p->name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16089 | v7_destructor_cb_t *cb = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16090 | (v7_destructor_cb_t *) v7_get_ptr(v7, p->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16091 | cb(v7, v7_get_ptr(v7, p->value)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16093 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16094 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16095 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16096 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16098 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16099 | o->base.entity_id_base = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16100 | o->base.entity_id_spec = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16101 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16102 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16104 | static void function_destructor(struct v7 *v7, void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16105 | struct v7_js_function *f = (struct v7_js_function *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16106 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16107 | if (f == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16109 | if (f->bcode != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16110 | release_bcode(v7, f->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16113 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16114 | f->base.entity_id_base = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16115 | f->base.entity_id_spec = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16116 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16117 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16118 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16119 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16120 | static void property_destructor(struct v7 *v7, void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16121 | struct v7_property *p = (struct v7_property *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16122 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16123 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16125 | p->entity_id = V7_ENTITY_ID_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16126 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16127 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16128 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16129 | struct v7 *v7_create(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16130 | struct v7_create_opts opts; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16131 | memset(&opts, 0, sizeof(opts)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16132 | return v7_create_opt(opts); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16133 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16135 | struct v7 *v7_create_opt(struct v7_create_opts opts) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16136 | struct v7 *v7 = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16137 | char z = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16139 | #if defined(HAS_V7_INFINITY) || defined(HAS_V7_NAN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16140 | double zero = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16141 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16143 | #ifdef HAS_V7_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 16144 | _v7_infinity = 1.0 / zero; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16145 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16146 | #ifdef HAS_V7_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 16147 | _v7_nan = zero / zero; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16148 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16150 | if (opts.object_arena_size == 0) opts.object_arena_size = 200; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16151 | if (opts.function_arena_size == 0) opts.function_arena_size = 100; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16152 | if (opts.property_arena_size == 0) opts.property_arena_size = 400; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16154 | if ((v7 = (struct v7 *) calloc(1, sizeof(*v7))) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16155 | #ifdef V7_STACK_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16156 | v7->sp_limit = (void *) ((uintptr_t) opts.c_stack_base - (V7_STACK_SIZE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16157 | v7->sp_lwm = opts.c_stack_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16158 | #ifdef V7_STACK_GUARD_MIN_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16159 | v7_sp_limit = v7->sp_limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16160 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16161 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16162 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16163 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16164 | v7->next_v7 = v7_head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16165 | v7_head = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16166 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16167 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16168 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16169 | v7->gc_next_asn = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16170 | v7->gc_min_asn = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16171 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16173 | v7->cur_dense_prop = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16174 | (struct v7_property *) calloc(1, sizeof(struct v7_property)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16175 | gc_arena_init(&v7->generic_object_arena, sizeof(struct v7_generic_object), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16176 | opts.object_arena_size, 10, "object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16177 | v7->generic_object_arena.destructor = generic_object_destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16178 | gc_arena_init(&v7->function_arena, sizeof(struct v7_js_function), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16179 | opts.function_arena_size, 10, "function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16180 | v7->function_arena.destructor = function_destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16181 | gc_arena_init(&v7->property_arena, sizeof(struct v7_property), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16182 | opts.property_arena_size, 10, "property"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16183 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16184 | v7->property_arena.destructor = property_destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16185 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16187 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16188 | * The compacting GC exploits the null terminator of the previous |
Marko Mikulicic |
0:c0ecb8bf28eb | 16189 | * string as marker. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16190 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16191 | mbuf_append(&v7->owned_strings, &z, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16192 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16193 | v7->inhibit_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16194 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16195 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16196 | v7->call_stack = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16197 | v7->bottom_call_frame = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16199 | #if defined(V7_THAW) && !defined(V7_FREEZE_NOT_READONLY) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16200 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16201 | struct v7_generic_object *obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16202 | v7->vals = *fr_vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16203 | v7->vals.global_object = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16204 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16205 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16206 | * The global object has to be mutable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16207 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16208 | obj = get_generic_object_struct(v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16209 | *obj = *get_generic_object_struct(fr_vals->global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16210 | obj->base.attributes &= ~(V7_OBJ_NOT_EXTENSIBLE | V7_OBJ_OFF_HEAP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16211 | v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16212 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16213 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 16214 | init_stdlib(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16215 | init_file(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16216 | init_crypto(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16217 | init_socket(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16218 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16220 | v7->inhibit_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16221 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16223 | return v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16224 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16226 | val_t v7_get_global(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16227 | return v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16228 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16229 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16230 | void v7_destroy(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16231 | if (v7 == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16232 | gc_arena_destroy(v7, &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16233 | gc_arena_destroy(v7, &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16234 | gc_arena_destroy(v7, &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16236 | mbuf_free(&v7->owned_strings); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16237 | mbuf_free(&v7->owned_values); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16238 | mbuf_free(&v7->foreign_strings); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16239 | mbuf_free(&v7->json_visited_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16240 | mbuf_free(&v7->tmp_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16241 | mbuf_free(&v7->act_bcodes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16242 | mbuf_free(&v7->stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16244 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16245 | /* delete this v7 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16246 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16247 | struct v7 *v, **prevp = &v7_head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16248 | for (v = v7_head; v != NULL; prevp = &v->next_v7, v = v->next_v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16249 | if (v == v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16250 | *prevp = v->next_v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16251 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16252 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16253 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16254 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16255 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16257 | free(v7->cur_dense_prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16258 | free(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16259 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16261 | v7_val_t v7_get_this(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16262 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16263 | * By default, when there's no active call frame, will return Global Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 16264 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16265 | v7_val_t ret = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16267 | struct v7_call_frame_base *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16268 | find_call_frame(v7, V7_CALL_FRAME_MASK_BCODE | V7_CALL_FRAME_MASK_CFUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16270 | if (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16271 | if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16272 | ret = ((struct v7_call_frame_bcode *) call_frame)->vals.this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16273 | } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16274 | ret = ((struct v7_call_frame_cfunc *) call_frame)->vals.this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16275 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16276 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16277 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16278 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16280 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16281 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16283 | V7_PRIVATE v7_val_t get_scope(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16284 | struct v7_call_frame_private *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16285 | (struct v7_call_frame_private *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 16286 | v7, V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16288 | if (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16289 | return call_frame->vals.scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16290 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16291 | /* No active call frame, return global object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16292 | return v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16293 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16294 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16296 | V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16297 | struct v7_call_frame_bcode *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16298 | (struct v7_call_frame_bcode *) find_call_frame(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16299 | V7_CALL_FRAME_MASK_BCODE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16300 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16301 | if (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16302 | return call_frame->bcode->strict_mode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16303 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16304 | /* No active call frame, assume no strict mode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16305 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16306 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16307 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16309 | v7_val_t v7_get_arguments(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16310 | return v7->vals.arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16311 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16312 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16313 | v7_val_t v7_arg(struct v7 *v7, unsigned long n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16314 | return v7_array_get(v7, v7->vals.arguments, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16315 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16317 | unsigned long v7_argc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16318 | return v7_array_length(v7, v7->vals.arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16319 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16321 | void v7_own(struct v7 *v7, v7_val_t *v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16322 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16323 | mbuf_append(&v7->owned_values, &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16324 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16325 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16327 | int v7_disown(struct v7 *v7, v7_val_t *v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16328 | v7_val_t **vp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16329 | (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16331 | for (; (char *) vp >= v7->owned_values.buf; vp--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16332 | if (*vp == v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16333 | *vp = *(v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - |
Marko Mikulicic |
0:c0ecb8bf28eb | 16334 | sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16335 | v7->owned_values.len -= sizeof(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16336 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16337 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16338 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16340 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16343 | void v7_set_gc_enabled(struct v7 *v7, int enabled) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16344 | v7->inhibit_gc = !enabled; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16345 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16347 | void v7_interrupt(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16348 | v7->interrupted = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16349 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16351 | const char *v7_get_parser_error(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16352 | return v7->error_msg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16355 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16357 | int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16358 | assert(what < V7_STACK_STATS_CNT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16359 | return v7->stack_stat[what]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16362 | void v7_stack_stat_clean(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16363 | memset(v7->stack_stat, 0x00, sizeof(v7->stack_stat)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16366 | #endif /* V7_ENABLE_STACK_TRACKING */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16367 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16368 | #line 1 "v7/src/primitive.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16369 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16370 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16371 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16372 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16373 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16375 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16376 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16377 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16379 | /* Number {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16381 | NOINSTR static v7_val_t mk_number(double v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16382 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16383 | /* not every NaN is a JS NaN */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16384 | if (isnan(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16385 | res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16386 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16387 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16388 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16389 | val_t r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16390 | } u; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16391 | u.d = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16392 | res = u.r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16394 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16395 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16397 | NOINSTR static double get_double(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16398 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16399 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16400 | val_t v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16401 | } u; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16402 | u.v = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16403 | /* Due to NaN packing, any non-numeric value is already a valid NaN value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16404 | return u.d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16405 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16406 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16407 | NOINSTR static v7_val_t mk_boolean(int v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16408 | return (!!v) | V7_TAG_BOOLEAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16409 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16411 | NOINSTR static int get_bool(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16412 | if (v7_is_boolean(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16413 | return v & 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16414 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16415 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16417 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16419 | NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16420 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16421 | return mk_number(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16422 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16424 | NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16425 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16426 | return get_double(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16427 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16429 | NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16430 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16431 | return (int) get_double(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16432 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16434 | int v7_is_number(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16435 | return v == V7_TAG_NAN || !isnan(get_double(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16436 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16438 | V7_PRIVATE int is_finite(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16439 | return v7_is_number(v) && v != V7_TAG_NAN && !isinf(v7_get_double(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16440 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16442 | /* }}} Number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16443 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16444 | /* Boolean {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16446 | NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16447 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16448 | return mk_boolean(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16449 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16451 | NOINSTR int v7_get_bool(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16452 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16453 | return get_bool(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16454 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16456 | int v7_is_boolean(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16457 | return (v & V7_TAG_MASK) == V7_TAG_BOOLEAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16458 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16460 | /* }}} Boolean */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16462 | /* null {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16464 | NOINSTR v7_val_t v7_mk_null(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16465 | return V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16466 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16467 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16468 | int v7_is_null(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16469 | return v == V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16470 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16472 | /* }}} null */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16474 | /* undefined {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16475 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16476 | NOINSTR v7_val_t v7_mk_undefined(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16477 | return V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16478 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16480 | int v7_is_undefined(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16481 | return v == V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16482 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16484 | /* }}} undefined */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16486 | /* Foreign {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16488 | V7_PRIVATE val_t pointer_to_value(void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16489 | uint64_t n = ((uint64_t)(uintptr_t) p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16491 | assert((n & V7_TAG_MASK) == 0 || (n & V7_TAG_MASK) == (~0 & V7_TAG_MASK)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16492 | return n & ~V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16493 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16494 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16495 | V7_PRIVATE void *get_ptr(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16496 | return (void *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16499 | NOINSTR void *v7_get_ptr(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16500 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16501 | if (!v7_is_foreign(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16502 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16503 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16504 | return get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16505 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16507 | NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16508 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16509 | return pointer_to_value(p) | V7_TAG_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16510 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16512 | int v7_is_foreign(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16513 | return (v & V7_TAG_MASK) == V7_TAG_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16514 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16515 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16516 | /* }}} Foreign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16517 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16518 | #line 1 "v7/src/function.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16519 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16520 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16521 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16522 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16523 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16525 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16526 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16527 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16528 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16529 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16530 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16532 | static val_t js_function_to_value(struct v7_js_function *o) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16533 | return pointer_to_value(o) | V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16534 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16536 | V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16537 | struct v7_js_function *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16538 | assert(is_js_function(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16539 | ret = (struct v7_js_function *) get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16540 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16541 | if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_JS_FUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16542 | fprintf(stderr, "entity_id: not a function!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16543 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16544 | } else if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16545 | fprintf(stderr, "entity_id: not an object!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16546 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16547 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16548 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16549 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16550 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16552 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16553 | val_t mk_js_function(struct v7 *v7, struct v7_generic_object *scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16554 | val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16555 | struct v7_js_function *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16556 | val_t fval = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16557 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16558 | tmp_stack_push(&tf, &proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16559 | tmp_stack_push(&tf, &fval); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16561 | f = new_function(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16563 | if (f == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16564 | /* fval is left `null` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16565 | goto cleanup; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16566 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16567 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16568 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16569 | f->base.entity_id_base = V7_ENTITY_ID_PART_OBJ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16570 | f->base.entity_id_spec = V7_ENTITY_ID_PART_JS_FUNC; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16571 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16573 | fval = js_function_to_value(f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16575 | f->base.properties = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16576 | f->scope = scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16578 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16579 | * Before setting a `V7_OBJ_FUNCTION` flag, make sure we don't have |
Marko Mikulicic |
0:c0ecb8bf28eb | 16580 | * `V7_OBJ_DENSE_ARRAY` flag set |
Marko Mikulicic |
0:c0ecb8bf28eb | 16581 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16582 | assert(!(f->base.attributes & V7_OBJ_DENSE_ARRAY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16583 | f->base.attributes |= V7_OBJ_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16584 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16585 | /* TODO(mkm): lazily create these properties on first access */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16586 | if (v7_is_object(proto)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16587 | v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), fval); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16588 | v7_def(v7, fval, "prototype", 9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16589 | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0), proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16590 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16592 | cleanup: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16593 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16594 | return fval; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16597 | V7_PRIVATE int is_js_function(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16598 | return (v & V7_TAG_MASK) == V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16599 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16601 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16602 | v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *f, int num_args) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16603 | val_t obj = mk_object(v7, v7->vals.function_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16604 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16605 | tmp_stack_push(&tf, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16606 | v7_def(v7, obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_cfunction(f)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16607 | if (num_args >= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16608 | v7_def(v7, obj, "length", 6, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16609 | V7_DESC_CONFIGURABLE(0)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16610 | v7_mk_number(v7, num_args)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16611 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16612 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16613 | return obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16614 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16616 | V7_PRIVATE v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16617 | v7_cfunction_t *f, int num_args, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16618 | v7_val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16619 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16620 | v7_val_t res = mk_cfunction_obj(v7, f, num_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16621 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16622 | tmp_stack_push(&tf, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16624 | v7_def(v7, res, "prototype", 9, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16625 | V7_DESC_CONFIGURABLE(0)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16626 | proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16627 | v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16628 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16629 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16632 | V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16633 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16634 | void *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16635 | v7_cfunction_t *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16636 | } u; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16637 | u.f = f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16638 | return pointer_to_value(u.p) | V7_TAG_CFUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16639 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16640 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16641 | V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16642 | v7_cfunction_t *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16644 | if (is_cfunction_lite(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16645 | /* Implementation is identical to get_ptr but is separate since |
Marko Mikulicic |
0:c0ecb8bf28eb | 16646 | * object pointers are not directly convertible to function pointers |
Marko Mikulicic |
0:c0ecb8bf28eb | 16647 | * according to ISO C and generates a warning in -Wpedantic mode. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16648 | ret = (v7_cfunction_t *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16649 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16650 | /* maybe cfunction object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16652 | /* extract the hidden property from a cfunction_object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16653 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16654 | p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16655 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16656 | /* yes, it's cfunction object. Extract cfunction pointer from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16657 | ret = get_cfunction_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16658 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16659 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16661 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16662 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16664 | V7_PRIVATE int is_cfunction_lite(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16665 | return (v & V7_TAG_MASK) == V7_TAG_CFUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16666 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16668 | V7_PRIVATE int is_cfunction_obj(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16669 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16670 | if (v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16671 | /* extract the hidden property from a cfunction_object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16672 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16673 | p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16674 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16675 | v = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16678 | ret = is_cfunction_lite(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16679 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16680 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16681 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16683 | v7_val_t v7_mk_function(struct v7 *v7, v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16684 | return mk_cfunction_obj(v7, f, -1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16685 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16687 | v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16688 | v7_val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16689 | return mk_cfunction_obj_with_proto(v7, f, ~0, proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16690 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16692 | v7_val_t v7_mk_cfunction(v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16693 | return mk_cfunction_lite(f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16694 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16696 | int v7_is_callable(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16697 | return is_js_function(v) || is_cfunction_lite(v) || is_cfunction_obj(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16698 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16699 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16700 | #line 1 "v7/src/exec.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16701 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16702 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16703 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16704 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16705 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16707 | /* osdep.h must be included before `cs_file.h` TODO(dfrank) : fix this */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16708 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16709 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16710 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16711 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16712 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16713 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16714 | /* Amalgamated: #include "v7/src/compiler.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16715 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16716 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16717 | enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16718 | return b_exec(v7, js_code, strlen(js_code), NULL, V7_UNDEFINED, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16719 | V7_UNDEFINED, 0, 0, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16720 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16722 | enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16723 | const struct v7_exec_opts *opts, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16724 | return b_exec(v7, js_code, strlen(js_code), opts->filename, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16725 | V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16726 | (opts->this_obj == 0 ? V7_UNDEFINED : opts->this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16727 | opts->is_json, 0, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16728 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16730 | enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16731 | return b_exec(v7, str, strlen(str), NULL, V7_UNDEFINED, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16732 | V7_UNDEFINED, 1, 0, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16733 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16735 | #ifndef V7_NO_FS |
Marko Mikulicic |
0:c0ecb8bf28eb | 16736 | static enum v7_err exec_file(struct v7 *v7, const char *path, val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16737 | int is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16738 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16739 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16740 | size_t file_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16741 | char *(*rd)(const char *, size_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16743 | rd = cs_read_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16744 | #ifdef V7_MMAP_EXEC |
Marko Mikulicic |
0:c0ecb8bf28eb | 16745 | rd = cs_mmap_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16746 | #ifdef V7_MMAP_EXEC_ONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 16747 | #define I_STRINGIFY(x) #x |
Marko Mikulicic |
0:c0ecb8bf28eb | 16748 | #define I_STRINGIFY2(x) I_STRINGIFY(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16749 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16750 | /* use mmap only for .js files */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16751 | if (strlen(path) <= 3 || strcmp(path + strlen(path) - 3, ".js") != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16752 | rd = cs_read_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16753 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16754 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16755 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16756 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16757 | if ((p = rd(path, &file_size)) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16758 | rcode = v7_throwf(v7, SYNTAX_ERROR, "cannot open [%s]", path); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16759 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16760 | * In order to maintain compat with existing API, we should save the |
Marko Mikulicic |
0:c0ecb8bf28eb | 16761 | * current exception value into `*res` |
Marko Mikulicic |
0:c0ecb8bf28eb | 16762 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 16763 | * TODO(dfrank): probably change API: clients can use |
Marko Mikulicic |
0:c0ecb8bf28eb | 16764 | *`v7_get_thrown_value()` now. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16765 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16766 | if (res != NULL) *res = v7_get_thrown_value(v7, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16767 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16768 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16769 | #ifndef V7_MMAP_EXEC |
Marko Mikulicic |
0:c0ecb8bf28eb | 16770 | int fr = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16771 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 16772 | int fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16773 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16774 | rcode = b_exec(v7, p, file_size, path, V7_UNDEFINED, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16775 | V7_UNDEFINED, is_json, fr, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16776 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16777 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16778 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16779 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16780 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16781 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16782 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16783 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16785 | enum v7_err v7_exec_file(struct v7 *v7, const char *path, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16786 | return exec_file(v7, path, res, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16789 | enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16790 | return exec_file(v7, path, res, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16791 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16792 | #endif /* V7_NO_FS */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16794 | enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16795 | v7_val_t args, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16796 | return b_apply(v7, func, this_obj, args, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16797 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16799 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 16800 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16801 | enum v7_err _v7_compile(const char *src, size_t js_code_size, int binary, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16802 | int use_bcode, FILE *fp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16803 | struct ast ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16804 | struct v7 *v7 = v7_create(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16805 | ast_off_t pos = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16806 | enum v7_err err; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16808 | v7->is_precompiling = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16810 | ast_init(&ast, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16811 | err = parse(v7, &ast, src, js_code_size, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16812 | if (err == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16813 | if (use_bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16814 | struct bcode bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16815 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16816 | * We don't set filename here, because the bcode will be just serialized |
Marko Mikulicic |
0:c0ecb8bf28eb | 16817 | * and then freed. We don't currently serialize filename. If we ever do, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16818 | * we'll have to make `_v7_compile()` to also take a filename argument, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16819 | * and use it here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16820 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16821 | bcode_init(&bcode, 0, NULL, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16822 | err = compile_script(v7, &ast, &bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16823 | if (err != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16824 | goto cleanup_bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16825 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16827 | if (binary) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16828 | bcode_serialize(v7, &bcode, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16829 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16830 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 16831 | dump_bcode(v7, fp, &bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16832 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 16833 | fprintf(stderr, "build flag V7_BCODE_DUMP not enabled\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16834 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16835 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16836 | cleanup_bcode: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16837 | bcode_free(v7, &bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16838 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16839 | if (binary) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16840 | fwrite(BIN_AST_SIGNATURE, sizeof(BIN_AST_SIGNATURE), 1, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16841 | fwrite(ast.mbuf.buf, ast.mbuf.len, 1, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16842 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16843 | ast_dump_tree(fp, &ast, &pos, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16845 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16848 | ast_free(&ast); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16849 | v7_destroy(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16850 | return err; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16851 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16853 | enum v7_err v7_compile(const char *src, int binary, int use_bcode, FILE *fp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16854 | return _v7_compile(src, strlen(src), binary, use_bcode, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16855 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16856 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16857 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16858 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16859 | #line 1 "v7/src/util.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16860 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16861 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16862 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16863 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16864 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16866 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16867 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16868 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16869 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16870 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16871 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16872 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16873 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16874 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16875 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16876 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16878 | void v7_print(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16879 | v7_fprint(stdout, v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16880 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16882 | void v7_fprint(FILE *f, struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16883 | char buf[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16884 | char *s = v7_stringify(v7, v, buf, sizeof(buf), V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16885 | fprintf(f, "%s", s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16886 | if (buf != s) free(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16887 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16889 | void v7_println(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16890 | v7_fprintln(stdout, v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16893 | void v7_fprintln(FILE *f, struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16894 | v7_fprint(f, v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16895 | fprintf(f, ENDL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16898 | void v7_fprint_stack_trace(FILE *f, struct v7 *v7, val_t e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16899 | size_t s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16900 | val_t strace_v = v7_get(v7, e, "stack", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16901 | const char *strace = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16902 | if (v7_is_string(strace_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16903 | strace = v7_get_string(v7, &strace_v, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16904 | fprintf(f, "%s\n", strace); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16906 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16907 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16908 | void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, val_t e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16909 | /* TODO(mkm): figure out if this is an error object and which kind */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16910 | v7_val_t msg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16911 | if (v7_is_undefined(e)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16912 | fprintf(f, "undefined error [%s]\n ", ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16913 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16914 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16915 | msg = v7_get(v7, e, "message", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16916 | if (v7_is_undefined(msg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16917 | msg = e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16918 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16919 | fprintf(f, "Exec error [%s]: ", ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16920 | v7_fprintln(f, v7, msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16921 | v7_fprint_stack_trace(f, v7, e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16924 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 16925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16926 | v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16927 | const v7_proxy_hnd_t *handler) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16928 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16929 | v7_val_t res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16930 | v7_val_t args = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16931 | v7_val_t handler_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16933 | v7_own(v7, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16934 | v7_own(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16935 | v7_own(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16936 | v7_own(v7, &target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16937 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16938 | /* if target is not an object, create one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16939 | if (!v7_is_object(target)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16940 | target = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16943 | /* prepare handler object with necessary properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16944 | handler_v = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16945 | if (handler->get != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16946 | set_cfunc_prop(v7, handler_v, "get", handler->get); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16947 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16948 | if (handler->set != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16949 | set_cfunc_prop(v7, handler_v, "set", handler->set); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16950 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16951 | if (handler->own_keys != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16952 | set_cfunc_prop(v7, handler_v, "ownKeys", handler->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16953 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16954 | if (handler->get_own_prop_desc != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16955 | v7_def(v7, handler_v, "_gpdc", ~0, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16956 | v7_mk_foreign(v7, (void *) handler->get_own_prop_desc)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16957 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16959 | /* prepare args */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16960 | args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16961 | v7_array_set(v7, args, 0, target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16962 | v7_array_set(v7, args, 1, handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16964 | /* call Proxy constructor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16965 | V7_TRY(b_apply(v7, v7_get(v7, v7->vals.global_object, "Proxy", ~0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16966 | v7_mk_object(v7), args, 1 /* as ctor */, &res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16968 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16969 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16970 | fprintf(stderr, "error during v7_mk_proxy()"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16971 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16974 | v7_disown(v7, &target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16975 | v7_disown(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16976 | v7_disown(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16977 | v7_disown(v7, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16978 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16979 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16981 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16983 | V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16984 | int tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16985 | if (v7_is_number(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16986 | return V7_TYPE_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16987 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16988 | tag = (v & V7_TAG_MASK) >> 48; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16989 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16990 | case V7_TAG_FOREIGN >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16991 | if (v7_is_null(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16992 | return V7_TYPE_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16993 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16994 | return V7_TYPE_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16995 | case V7_TAG_UNDEFINED >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16996 | return V7_TYPE_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16997 | case V7_TAG_OBJECT >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16998 | if (v7_get_proto(v7, v) == v7->vals.array_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16999 | return V7_TYPE_ARRAY_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17000 | } else if (v7_get_proto(v7, v) == v7->vals.boolean_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17001 | return V7_TYPE_BOOLEAN_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17002 | } else if (v7_get_proto(v7, v) == v7->vals.string_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17003 | return V7_TYPE_STRING_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17004 | } else if (v7_get_proto(v7, v) == v7->vals.number_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17005 | return V7_TYPE_NUMBER_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17006 | } else if (v7_get_proto(v7, v) == v7->vals.function_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17007 | return V7_TYPE_CFUNCTION_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17008 | } else if (v7_get_proto(v7, v) == v7->vals.date_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17009 | return V7_TYPE_DATE_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17010 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17011 | return V7_TYPE_GENERIC_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17012 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17013 | case V7_TAG_STRING_I >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17014 | case V7_TAG_STRING_O >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17015 | case V7_TAG_STRING_F >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17016 | case V7_TAG_STRING_D >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17017 | case V7_TAG_STRING_5 >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17018 | return V7_TYPE_STRING; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17019 | case V7_TAG_BOOLEAN >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17020 | return V7_TYPE_BOOLEAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17021 | case V7_TAG_FUNCTION >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17022 | return V7_TYPE_FUNCTION_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17023 | case V7_TAG_CFUNCTION >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17024 | return V7_TYPE_CFUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17025 | case V7_TAG_REGEXP >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17026 | return V7_TYPE_REGEXP_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17027 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17028 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17029 | return V7_TYPE_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17030 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17031 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17033 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17034 | V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17035 | if ((b & 0x01) != (b >> 7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17036 | b ^= 0x81; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17038 | return b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17040 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17041 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 17042 | #line 1 "v7/src/string.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 17043 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17044 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17045 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 17046 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 17047 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17048 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17049 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17050 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17051 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17052 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17053 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17054 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17055 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17056 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17057 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17058 | /* Amalgamated: #include "v7/src/heapusage.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17060 | /* TODO(lsm): NaN payload location depends on endianness, make crossplatform */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17061 | #define GET_VAL_NAN_PAYLOAD(v) ((char *) &(v)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17063 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17064 | * Dictionary of read-only strings with length > 5. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17065 | * NOTE(lsm): must be sorted lexicographically, because |
Marko Mikulicic |
0:c0ecb8bf28eb | 17066 | * v_find_string_in_dictionary performs binary search over this list. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17067 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17068 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17069 | static const struct v7_vec_const v_dictionary_strings[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17070 | V7_VEC(" is not a function"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17071 | V7_VEC("Boolean"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17072 | V7_VEC("Crypto"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17073 | V7_VEC("EvalError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17074 | V7_VEC("Function"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17075 | V7_VEC("Infinity"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17076 | V7_VEC("InternalError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17077 | V7_VEC("LOG10E"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17078 | V7_VEC("MAX_VALUE"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17079 | V7_VEC("MIN_VALUE"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17080 | V7_VEC("NEGATIVE_INFINITY"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17081 | V7_VEC("Number"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17082 | V7_VEC("Object"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17083 | V7_VEC("POSITIVE_INFINITY"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17084 | V7_VEC("RangeError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17085 | V7_VEC("ReferenceError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17086 | V7_VEC("RegExp"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17087 | V7_VEC("SQRT1_2"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17088 | V7_VEC("Socket"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17089 | V7_VEC("String"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17090 | V7_VEC("SyntaxError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17091 | V7_VEC("TypeError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17092 | V7_VEC("UBJSON"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17093 | V7_VEC("_modcache"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17094 | V7_VEC("accept"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17095 | V7_VEC("arguments"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17096 | V7_VEC("base64_decode"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17097 | V7_VEC("base64_encode"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17098 | V7_VEC("boolean"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17099 | V7_VEC("charAt"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17100 | V7_VEC("charCodeAt"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17101 | V7_VEC("concat"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17102 | V7_VEC("configurable"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17103 | V7_VEC("connect"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17104 | V7_VEC("constructor"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17105 | V7_VEC("create"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17106 | V7_VEC("defineProperties"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17107 | V7_VEC("defineProperty"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17108 | V7_VEC("every"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17109 | V7_VEC("exists"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17110 | V7_VEC("exports"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17111 | V7_VEC("filter"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17112 | V7_VEC("forEach"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17113 | V7_VEC("fromCharCode"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17114 | V7_VEC("function"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17115 | V7_VEC("getDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17116 | V7_VEC("getDay"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17117 | V7_VEC("getFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17118 | V7_VEC("getHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17119 | V7_VEC("getMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17120 | V7_VEC("getMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17121 | V7_VEC("getMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17122 | V7_VEC("getOwnPropertyDescriptor"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17123 | V7_VEC("getOwnPropertyNames"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17124 | V7_VEC("getPrototypeOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17125 | V7_VEC("getSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17126 | V7_VEC("getTime"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17127 | V7_VEC("getTimezoneOffset"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17128 | V7_VEC("getUTCDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17129 | V7_VEC("getUTCDay"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17130 | V7_VEC("getUTCFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17131 | V7_VEC("getUTCHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17132 | V7_VEC("getUTCMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17133 | V7_VEC("getUTCMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17134 | V7_VEC("getUTCMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17135 | V7_VEC("getUTCSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17136 | V7_VEC("global"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17137 | V7_VEC("hasOwnProperty"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17138 | V7_VEC("ignoreCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17139 | V7_VEC("indexOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17140 | V7_VEC("isArray"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17141 | V7_VEC("isExtensible"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17142 | V7_VEC("isFinite"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17143 | V7_VEC("isPrototypeOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17144 | V7_VEC("lastIndex"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17145 | V7_VEC("lastIndexOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17146 | V7_VEC("length"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17147 | V7_VEC("listen"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17148 | V7_VEC("loadJSON"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17149 | V7_VEC("localeCompare"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17150 | V7_VEC("md5_hex"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17151 | V7_VEC("module"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17152 | V7_VEC("multiline"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17153 | V7_VEC("number"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17154 | V7_VEC("parseFloat"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17155 | V7_VEC("parseInt"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17156 | V7_VEC("preventExtensions"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17157 | V7_VEC("propertyIsEnumerable"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17158 | V7_VEC("prototype"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17159 | V7_VEC("random"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17160 | V7_VEC("recvAll"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17161 | V7_VEC("reduce"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17162 | V7_VEC("remove"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17163 | V7_VEC("rename"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17164 | V7_VEC("render"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17165 | V7_VEC("replace"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17166 | V7_VEC("require"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17167 | V7_VEC("reverse"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17168 | V7_VEC("search"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17169 | V7_VEC("setDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17170 | V7_VEC("setFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17171 | V7_VEC("setHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17172 | V7_VEC("setMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17173 | V7_VEC("setMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17174 | V7_VEC("setMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17175 | V7_VEC("setSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17176 | V7_VEC("setTime"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17177 | V7_VEC("setUTCDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17178 | V7_VEC("setUTCFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17179 | V7_VEC("setUTCHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17180 | V7_VEC("setUTCMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17181 | V7_VEC("setUTCMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17182 | V7_VEC("setUTCMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17183 | V7_VEC("setUTCSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17184 | V7_VEC("sha1_hex"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17185 | V7_VEC("source"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17186 | V7_VEC("splice"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17187 | V7_VEC("string"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17188 | V7_VEC("stringify"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17189 | V7_VEC("substr"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17190 | V7_VEC("substring"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17191 | V7_VEC("toDateString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17192 | V7_VEC("toExponential"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17193 | V7_VEC("toFixed"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17194 | V7_VEC("toISOString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17195 | V7_VEC("toJSON"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17196 | V7_VEC("toLocaleDateString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17197 | V7_VEC("toLocaleLowerCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17198 | V7_VEC("toLocaleString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17199 | V7_VEC("toLocaleTimeString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17200 | V7_VEC("toLocaleUpperCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17201 | V7_VEC("toLowerCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17202 | V7_VEC("toPrecision"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17203 | V7_VEC("toString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17204 | V7_VEC("toTimeString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17205 | V7_VEC("toUTCString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17206 | V7_VEC("toUpperCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17207 | V7_VEC("valueOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17208 | V7_VEC("writable"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17209 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17210 | /* clang-format on */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17212 | int nextesc(const char **p); /* from SLRE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17213 | V7_PRIVATE size_t unescape(const char *s, size_t len, char *to) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17214 | const char *end = s + len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17215 | size_t n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17216 | char tmp[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17217 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17218 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17219 | while (s < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17220 | s += chartorune(&r, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17221 | if (r == '\\' && s < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17222 | switch (*s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17223 | case '"': |
Marko Mikulicic |
0:c0ecb8bf28eb | 17224 | s++, r = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17225 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17226 | case '\'': |
Marko Mikulicic |
0:c0ecb8bf28eb | 17227 | s++, r = '\''; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17228 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17229 | case '\n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 17230 | s++, r = '\n'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17231 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17232 | default: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17233 | const char *tmp_s = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17234 | int i = nextesc(&s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17235 | switch (i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17236 | case -SLRE_INVALID_ESC_CHAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17237 | r = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17238 | s = tmp_s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17239 | n += runetochar(to == NULL ? tmp : to + n, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17240 | s += chartorune(&r, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17241 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17242 | case -SLRE_INVALID_HEX_DIGIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17243 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17244 | r = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17245 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17246 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17247 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17248 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17249 | n += runetochar(to == NULL ? tmp : to + n, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17252 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17253 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17255 | static int v_find_string_in_dictionary(const char *s, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17256 | size_t start = 0, end = ARRAY_SIZE(v_dictionary_strings); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17257 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17258 | while (s != NULL && start < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17259 | size_t mid = start + (end - start) / 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17260 | const struct v7_vec_const *v = &v_dictionary_strings[mid]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17261 | size_t min_len = len < v->len ? len : v->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17262 | int comparison_result = memcmp(s, v->p, min_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17263 | if (comparison_result == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17264 | comparison_result = len - v->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17265 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17266 | if (comparison_result < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17267 | end = mid; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17268 | } else if (comparison_result > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17269 | start = mid + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17270 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17271 | return mid; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17272 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17273 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17274 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17275 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17277 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 17278 | V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, val_t obj, val_t arg, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17279 | double *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17280 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17281 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17282 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17283 | const char *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17284 | double at = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17286 | *res = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17288 | rcode = to_string(v7, obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17289 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17290 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17291 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17293 | p = v7_get_string(v7, &s, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17295 | n = utfnlen(p, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17296 | if (v7_is_number(arg) && at >= 0 && at < n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17297 | Rune r = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17298 | p = utfnshift(p, at); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17299 | chartorune(&r, (char *) p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17300 | *res = r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17301 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17302 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17303 | *res = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17304 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17305 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17307 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17308 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17309 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17311 | V7_PRIVATE int s_cmp(struct v7 *v7, val_t a, val_t b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17312 | size_t a_len, b_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17313 | const char *a_ptr, *b_ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17315 | a_ptr = v7_get_string(v7, &a, &a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17316 | b_ptr = v7_get_string(v7, &b, &b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17318 | if (a_len == b_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17319 | return memcmp(a_ptr, b_ptr, a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17321 | if (a_len > b_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17322 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17323 | } else if (a_len < b_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17324 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17325 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17326 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17327 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17328 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17330 | V7_PRIVATE val_t s_concat(struct v7 *v7, val_t a, val_t b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17331 | size_t a_len, b_len, res_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17332 | const char *a_ptr, *b_ptr, *res_ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17333 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17334 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17335 | /* Find out lengths of both srtings */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17336 | a_ptr = v7_get_string(v7, &a, &a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17337 | b_ptr = v7_get_string(v7, &b, &b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17339 | /* Create an placeholder string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17340 | res = v7_mk_string(v7, NULL, a_len + b_len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17342 | /* v7_mk_string() may have reallocated mbuf - revalidate pointers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17343 | a_ptr = v7_get_string(v7, &a, &a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17344 | b_ptr = v7_get_string(v7, &b, &b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17346 | /* Copy strings into the placeholder */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17347 | res_ptr = v7_get_string(v7, &res, &res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17348 | memcpy((char *) res_ptr, a_ptr, a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17349 | memcpy((char *) res_ptr + a_len, b_ptr, b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17351 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17352 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17354 | V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17355 | char *e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17356 | unsigned long res = strtoul(s, &e, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17357 | *ok = (e == s + len) && len != 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17358 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17361 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 17362 | V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17363 | unsigned long *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17364 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17365 | char buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17366 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17367 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17368 | V7_TRY(to_string(v7, v, NULL, buf, sizeof(buf), &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17370 | *res = cstr_to_ulong(buf, len, ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17371 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17372 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17373 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17374 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17376 | /* Insert a string into mbuf at specified offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17377 | V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17378 | size_t len, uint8_t /*enum embstr_flags*/ flags) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17379 | char *old_base = m->buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17380 | uint8_t p_backed_by_mbuf = p >= old_base && p < old_base + m->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17381 | size_t n = (flags & EMBSTR_UNESCAPE) ? unescape(p, len, NULL) : len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17383 | /* Calculate how many bytes length takes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17384 | int k = calc_llen(n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17386 | /* total length: varing length + string len + zero-term */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17387 | size_t tot_len = k + n + !!(flags & EMBSTR_ZERO_TERM); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17389 | /* Allocate buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17390 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17391 | mbuf_insert(m, offset, NULL, tot_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17392 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17394 | /* Fixup p if it was relocated by mbuf_insert() above */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17395 | if (p_backed_by_mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17396 | p += m->buf - old_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17397 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17398 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17399 | /* Write length */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17400 | encode_varint(n, (unsigned char *) m->buf + offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17402 | /* Write string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17403 | if (p != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17404 | if (flags & EMBSTR_UNESCAPE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17405 | unescape(p, len, m->buf + offset + k); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17406 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17407 | memcpy(m->buf + offset + k, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17408 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17409 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17411 | /* add NULL-terminator if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17412 | if (flags & EMBSTR_ZERO_TERM) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17413 | m->buf[offset + tot_len - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17414 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17415 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17417 | /* Create a string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17418 | v7_val_t v7_mk_string(struct v7 *v7, const char *p, size_t len, int copy) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17419 | struct mbuf *m = copy ? &v7->owned_strings : &v7->foreign_strings; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17420 | val_t offset = m->len, tag = V7_TAG_STRING_F; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17421 | int dict_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17422 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17423 | #ifdef V7_GC_AFTER_STRING_ALLOC |
Marko Mikulicic |
0:c0ecb8bf28eb | 17424 | v7->need_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17425 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17427 | if (len == ~((size_t) 0)) len = strlen(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17429 | if (len <= 4) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17430 | char *s = GET_VAL_NAN_PAYLOAD(offset) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17431 | offset = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17432 | if (p != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17433 | memcpy(s, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17434 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17435 | s[-1] = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17436 | tag = V7_TAG_STRING_I; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17437 | } else if (len == 5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17438 | char *s = GET_VAL_NAN_PAYLOAD(offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17439 | offset = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17440 | if (p != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17441 | memcpy(s, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17442 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17443 | tag = V7_TAG_STRING_5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17444 | } else if ((dict_index = v_find_string_in_dictionary(p, len)) >= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17445 | offset = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17446 | GET_VAL_NAN_PAYLOAD(offset)[0] = dict_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17447 | tag = V7_TAG_STRING_D; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17448 | } else if (copy) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17449 | compute_need_gc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17451 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17452 | * Before embedding new string, check if the reallocation is needed. If |
Marko Mikulicic |
0:c0ecb8bf28eb | 17453 | * so, perform the reallocation by calling `mbuf_resize` manually, since we |
Marko Mikulicic |
0:c0ecb8bf28eb | 17454 | * need to preallocate some extra space (`_V7_STRING_BUF_RESERVE`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17455 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17456 | if ((m->len + len) > m->size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17457 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17458 | mbuf_resize(m, m->len + len + _V7_STRING_BUF_RESERVE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17459 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17461 | embed_string(m, m->len, p, len, EMBSTR_ZERO_TERM); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17462 | tag = V7_TAG_STRING_O; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17463 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17464 | /* TODO(imax): panic if offset >= 2^32. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17465 | offset |= ((val_t) gc_next_allocation_seqn(v7, p, len)) << 32; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17466 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17467 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17468 | /* foreign string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17469 | if (sizeof(void *) <= 4 && len <= UINT16_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17470 | /* small foreign strings can fit length and ptr in the val_t */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17471 | offset = (uint64_t) len << 32 | (uint64_t)(uintptr_t) p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17472 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17473 | /* bigger strings need indirection that uses ram */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17474 | size_t pos = m->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17475 | int llen = calc_llen(len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17477 | /* allocate space for len and ptr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17478 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17479 | mbuf_insert(m, pos, NULL, llen + sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17480 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17481 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17482 | encode_varint(len, (uint8_t *) (m->buf + pos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17483 | memcpy(m->buf + pos + llen, &p, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17484 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17485 | tag = V7_TAG_STRING_F; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17486 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17488 | /* NOTE(lsm): don't use pointer_to_value, 32-bit ptrs will truncate */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17489 | return (offset & ~V7_TAG_MASK) | tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17490 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17492 | int v7_is_string(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17493 | uint64_t t = v & V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17494 | return t == V7_TAG_STRING_I || t == V7_TAG_STRING_F || t == V7_TAG_STRING_O || |
Marko Mikulicic |
0:c0ecb8bf28eb | 17495 | t == V7_TAG_STRING_5 || t == V7_TAG_STRING_D; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17497 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17498 | /* Get a pointer to string and string length. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17499 | const char *v7_get_string(struct v7 *v7, val_t *v, size_t *sizep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17500 | uint64_t tag = v[0] & V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17501 | const char *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17502 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17503 | size_t size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17505 | if (!v7_is_string(*v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17506 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17507 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17509 | if (tag == V7_TAG_STRING_I) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17510 | p = GET_VAL_NAN_PAYLOAD(*v) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17511 | size = p[-1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17512 | } else if (tag == V7_TAG_STRING_5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17513 | p = GET_VAL_NAN_PAYLOAD(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17514 | size = 5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17515 | } else if (tag == V7_TAG_STRING_D) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17516 | int index = ((unsigned char *) GET_VAL_NAN_PAYLOAD(*v))[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17517 | size = v_dictionary_strings[index].len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17518 | p = v_dictionary_strings[index].p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17519 | } else if (tag == V7_TAG_STRING_O) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17520 | size_t offset = (size_t) gc_string_val_to_offset(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17521 | char *s = v7->owned_strings.buf + offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17523 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17524 | gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17525 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17527 | size = decode_varint((uint8_t *) s, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17528 | p = s + llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17529 | } else if (tag == V7_TAG_STRING_F) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17530 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17531 | * short foreign strings on <=32-bit machines can be encoded in a compact |
Marko Mikulicic |
0:c0ecb8bf28eb | 17532 | * form: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17533 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17534 | * 7 6 5 4 3 2 1 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 17535 | * 11111111|1111tttt|llllllll|llllllll|ssssssss|ssssssss|ssssssss|ssssssss |
Marko Mikulicic |
0:c0ecb8bf28eb | 17536 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17537 | * Strings longer than 2^26 will be indireceted through the foreign_strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 17538 | * mbuf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17539 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17540 | * We don't use a different tag to represent those two cases. Instead, all |
Marko Mikulicic |
0:c0ecb8bf28eb | 17541 | * foreign strings represented with the help of the foreign_strings mbuf |
Marko Mikulicic |
0:c0ecb8bf28eb | 17542 | * will have the upper 16-bits of the payload set to zero. This allows us to |
Marko Mikulicic |
0:c0ecb8bf28eb | 17543 | * represent up to 477 million foreign strings longer than 64k. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17544 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17545 | uint16_t len = (*v >> 32) & 0xFFFF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17546 | if (sizeof(void *) <= 4 && len != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17547 | size = (size_t) len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17548 | p = (const char *) (uintptr_t) *v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17549 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17550 | size_t offset = (size_t) gc_string_val_to_offset(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17551 | char *s = v7->foreign_strings.buf + offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17552 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17553 | size = decode_varint((uint8_t *) s, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17554 | memcpy(&p, s + llen, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17555 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17556 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17557 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17558 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17560 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17561 | if (sizep != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17562 | *sizep = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17563 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17564 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17565 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17567 | const char *v7_get_cstring(struct v7 *v7, v7_val_t *value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17568 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17569 | const char *s = v7_get_string(v7, value, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17570 | if (s == NULL) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17571 | if (s[size] != 0 || strlen(s) != size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17572 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17573 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17574 | return s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17575 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17576 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 17577 | #line 1 "v7/src/array.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 17578 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17579 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17580 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 17581 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 17582 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17584 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17585 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17586 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17587 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17588 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17589 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17590 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17591 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17593 | /* like c_snprintf but returns `size` if write is truncated */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17594 | static int v_sprintf_s(char *buf, size_t size, const char *fmt, ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17595 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17596 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17597 | va_start(ap, fmt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17598 | n = c_vsnprintf(buf, size, fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17599 | if (n > size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17600 | return size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17601 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17602 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17603 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17605 | v7_val_t v7_mk_array(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17606 | val_t a = mk_object(v7, v7->vals.array_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17607 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 17608 | v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17609 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17610 | return a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17611 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17612 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17613 | int v7_is_array(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17614 | return v7_is_generic_object(v) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 17615 | is_prototype_of(v7, v, v7->vals.array_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17616 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17618 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17619 | * Dense arrays are backed by mbuf. Currently the array can only grow by |
Marko Mikulicic |
0:c0ecb8bf28eb | 17620 | * appending (i.e. setting an element whose index == array.length) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17621 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17622 | * TODO(mkm): automatically promote dense arrays to normal objects |
Marko Mikulicic |
0:c0ecb8bf28eb | 17623 | * when they are used as sparse arrays or to store arbitrary keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 17624 | * (perhaps a hybrid approach) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17625 | * TODO(mkm): small sparsness doesn't have to promote the array, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17626 | * we can just fill empty slots with a tag. In JS missing array |
Marko Mikulicic |
0:c0ecb8bf28eb | 17627 | * indices are subtly different from indices with an undefined value |
Marko Mikulicic |
0:c0ecb8bf28eb | 17628 | * (key iteration). |
Marko Mikulicic |
0:c0ecb8bf28eb | 17629 | * TODO(mkm): change the interpreter so it can set elements in dense arrays |
Marko Mikulicic |
0:c0ecb8bf28eb | 17630 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17631 | V7_PRIVATE val_t v7_mk_dense_array(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17632 | val_t a = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17633 | #ifdef V7_ENABLE_DENSE_ARRAYS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17634 | v7_own(v7, &a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17635 | v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17637 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17638 | * Before setting a `V7_OBJ_DENSE_ARRAY` flag, make sure we don't have |
Marko Mikulicic |
0:c0ecb8bf28eb | 17639 | * `V7_OBJ_FUNCTION` flag set |
Marko Mikulicic |
0:c0ecb8bf28eb | 17640 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17641 | assert(!(get_object_struct(a)->attributes & V7_OBJ_FUNCTION)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17642 | get_object_struct(a)->attributes |= V7_OBJ_DENSE_ARRAY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17644 | v7_disown(v7, &a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17645 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17646 | return a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17647 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17649 | /* TODO_V7_ERR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17650 | val_t v7_array_get(struct v7 *v7, val_t arr, unsigned long index) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17651 | return v7_array_get2(v7, arr, index, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17652 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17654 | /* TODO_V7_ERR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17655 | val_t v7_array_get2(struct v7 *v7, val_t arr, unsigned long index, int *has) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17656 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17657 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17659 | if (has != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17660 | *has = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17661 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17662 | if (v7_is_object(arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17663 | if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17664 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17665 | v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17666 | struct mbuf *abuf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17667 | unsigned long len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17668 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17669 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17670 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17671 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17672 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17673 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17674 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17675 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17676 | if (index >= len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17677 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17678 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17679 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17680 | memcpy(&res, abuf->buf + index * sizeof(val_t), sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17681 | if (has != NULL && res != V7_TAG_NOVALUE) *has = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17682 | if (res == V7_TAG_NOVALUE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17683 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17685 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17686 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17687 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17688 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17689 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17690 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17691 | p = v7_get_property(v7, arr, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17692 | if (has != NULL && p != NULL) *has = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17693 | V7_TRY(v7_property_value(v7, arr, p, &res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17694 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17695 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17696 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17697 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17698 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17701 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17702 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17703 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17704 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17706 | #if V7_ENABLE_DENSE_ARRAYS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17708 | /* Create V7 strings for integers such as array indices */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17709 | static val_t ulong_to_str(struct v7 *v7, unsigned long n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17710 | char buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17711 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17712 | len = c_snprintf(buf, sizeof(buf), "%lu", n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17713 | return v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17714 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17716 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17717 | * Pack 15-bit length and 15 bit index, leaving 2 bits for tag. the LSB has to |
Marko Mikulicic |
0:c0ecb8bf28eb | 17718 | * be set to distinguish it from a prop pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17719 | * In alternative we just fetch the length from obj at each call to v7_next_prop |
Marko Mikulicic |
0:c0ecb8bf28eb | 17720 | * and just stuff the index here (e.g. on 8/16-bit platforms). |
Marko Mikulicic |
0:c0ecb8bf28eb | 17721 | * TODO(mkm): conditional for 16-bit platforms |
Marko Mikulicic |
0:c0ecb8bf28eb | 17722 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17723 | #define PACK_ITER(len, idx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17724 | ((struct v7_property *) ((len) << 17 | (idx) << 1 | 1)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17725 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17726 | #define UNPACK_ITER_LEN(p) (((uintptr_t) p) >> 17) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17727 | #define UNPACK_ITER_IDX(p) ((((uintptr_t) p) >> 1) & 0x7FFF) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17728 | #define IS_PACKED_ITER(p) ((uintptr_t) p & 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17730 | void *v7_next_prop(struct v7 *v7, val_t obj, void *h, val_t *name, val_t *val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17731 | v7_prop_attr_t *attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17732 | struct v7_property *p = (struct v7_property *) h; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17733 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17734 | if (get_object_struct(obj)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17735 | /* This is a dense array. Find backing mbuf and fetch values from there */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17736 | struct v7_property *hp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17737 | v7_get_own_property2(v7, obj, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17738 | struct mbuf *abuf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17739 | unsigned long len, idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17740 | if (hp != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17741 | abuf = (struct mbuf *) v7_get_ptr(v7, hp->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17742 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17743 | if (abuf == NULL) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17744 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17745 | if (len == 0) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17746 | idx = (p == NULL) ? 0 : UNPACK_ITER_IDX(p) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17747 | p = (idx == len) ? get_object_struct(obj)->properties : PACK_ITER(len, idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17748 | if (val != NULL) *val = ((val_t *) abuf->buf)[idx]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17749 | if (attrs != NULL) *attrs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17750 | if (name != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17751 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17752 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17753 | *name = v7_mk_string(v7, buf, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17754 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17755 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17756 | /* Ordinary object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17757 | p = (p == NULL) ? get_object_struct(obj)->properties : p->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17758 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17759 | if (name != NULL) *name = p->name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17760 | if (val != NULL) *val = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17761 | if (attrs != NULL) *attrs = p->attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17762 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17763 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17764 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17765 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17768 | V7_PRIVATE val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 17769 | v7_iter_get_value(struct v7 *v7, val_t obj, struct v7_property *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17770 | return IS_PACKED_ITER(p) ? v7_array_get(v7, obj, UNPACK_ITER_IDX(p)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17771 | : p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17772 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17773 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17774 | V7_PRIVATE val_t v7_iter_get_name(struct v7 *v7, struct v7_property *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17775 | return IS_PACKED_ITER(p) ? ulong_to_str(v7, UNPACK_ITER_IDX(p)) : p->name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17776 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17778 | V7_PRIVATE uint8_t v7_iter_get_attrs(struct v7_property *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17779 | return IS_PACKED_ITER(p) ? 0 : p->attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17780 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17781 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17782 | /* return array index as number or undefined. works with iterators */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17783 | V7_PRIVATE enum v7_err v7_iter_get_index(struct v7 *v7, struct v7_property *p, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17784 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17785 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17786 | int ok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17787 | unsigned long res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17788 | if (IS_PACKED_ITER(p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17789 | *res = v7_mk_number(v7, UNPACK_ITER_IDX(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17790 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17791 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17792 | V7_TRY(str_to_ulong(v7, p->name, &ok, &res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17793 | if (!ok || res >= UINT32_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17794 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17796 | *res = v7_mk_number(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17797 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17799 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17800 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17801 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17802 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17804 | /* TODO_V7_ERR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17805 | unsigned long v7_array_length(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17806 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17807 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17808 | unsigned long len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17810 | if (!v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17811 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17812 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17813 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17815 | #if V7_ENABLE_DENSE_ARRAYS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17816 | if (get_object_struct(v)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17817 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17818 | v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17819 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17820 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17821 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17822 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17823 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17824 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17825 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17826 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17827 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17828 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17829 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17830 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17831 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17832 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17834 | for (p = get_object_struct(v)->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17835 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17836 | unsigned long n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17837 | V7_TRY(str_to_ulong(v7, p->name, &ok, &n)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17838 | if (ok && n >= len && n < UINT32_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17839 | len = n + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17840 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17841 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17843 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17844 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17845 | return len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17848 | int v7_array_set(struct v7 *v7, val_t arr, unsigned long index, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17849 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17850 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17851 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17852 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17854 | rcode = v7_array_set_throwing(v7, arr, index, v, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17855 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17856 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17857 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17858 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17859 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17860 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17861 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17862 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17864 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17865 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17868 | enum v7_err v7_array_set_throwing(struct v7 *v7, val_t arr, unsigned long index, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17869 | val_t v, int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17870 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17871 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17873 | if (v7_is_object(arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17874 | if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17875 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17876 | v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17877 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17878 | unsigned long len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17879 | assert(p != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17880 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17882 | if (get_object_struct(arr)->attributes & V7_OBJ_NOT_EXTENSIBLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17883 | if (is_strict_mode(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17884 | rcode = v7_throwf(v7, TYPE_ERROR, "Object is not extensible"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17885 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17888 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17889 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17890 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17891 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17892 | abuf = (struct mbuf *) malloc(sizeof(*abuf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17893 | mbuf_init(abuf, sizeof(val_t) * (index + 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17894 | p->value = v7_mk_foreign(v7, abuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17895 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17896 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17897 | /* TODO(mkm): possibly promote to sparse array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17898 | if (index > len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17899 | unsigned long i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17900 | val_t s = V7_TAG_NOVALUE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17901 | for (i = len; i < index; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17902 | mbuf_append(abuf, (char *) &s, sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17903 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17904 | len = index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17907 | if (index == len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17908 | mbuf_append(abuf, (char *) &v, sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17909 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17910 | memcpy(abuf->buf + index * sizeof(val_t), &v, sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17911 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17912 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17913 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17914 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17915 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17916 | struct v7_property *tmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17917 | rcode = set_property(v7, arr, buf, n, v, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17918 | ires = (tmp == NULL) ? -1 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17920 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17921 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17923 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17924 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17926 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17927 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17928 | *res = ires; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17929 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17930 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17931 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17933 | void v7_array_del(struct v7 *v7, val_t arr, unsigned long index) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17934 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17935 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17936 | v7_del(v7, arr, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17937 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17939 | int v7_array_push(struct v7 *v7, v7_val_t arr, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17940 | return v7_array_set(v7, arr, v7_array_length(v7, arr), v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17943 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 17944 | enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17945 | int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17946 | return v7_array_set_throwing(v7, arr, v7_array_length(v7, arr), v, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17947 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17948 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 17949 | #line 1 "v7/src/object.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 17950 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17951 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17952 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 17953 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 17954 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17956 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17957 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17958 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17959 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17960 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17961 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17962 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17963 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17964 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17965 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17966 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17967 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17968 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17970 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17971 | * Default property attributes (see `v7_prop_attr_t`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17972 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17973 | #define V7_DEFAULT_PROPERTY_ATTRS 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 17974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17975 | V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17976 | struct v7_generic_object *o = new_generic_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17977 | if (o == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17978 | return V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17979 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17980 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17981 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17982 | o->base.entity_id_base = V7_ENTITY_ID_PART_OBJ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17983 | o->base.entity_id_spec = V7_ENTITY_ID_PART_GEN_OBJ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17984 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17985 | o->base.properties = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17986 | obj_prototype_set(v7, &o->base, get_object_struct(prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17987 | return v7_object_to_value(&o->base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17988 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17989 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17990 | v7_val_t v7_mk_object(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17991 | return mk_object(v7, v7->vals.object_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17994 | V7_PRIVATE val_t v7_object_to_value(struct v7_object *o) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17995 | if (o == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17996 | return V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17997 | } else if (o->attributes & V7_OBJ_FUNCTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17998 | return pointer_to_value(o) | V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17999 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18000 | return pointer_to_value(o) | V7_TAG_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18001 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18002 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18003 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18004 | V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18005 | struct v7_generic_object *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18006 | if (v7_is_null(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18007 | ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18008 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18009 | assert(v7_is_generic_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18010 | ret = (struct v7_generic_object *) get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18011 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18012 | if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18013 | fprintf(stderr, "not a generic object!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18014 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18015 | } else if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_GEN_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18016 | fprintf(stderr, "not an object (but is a generic object)!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18017 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18019 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18020 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18021 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18022 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18024 | V7_PRIVATE struct v7_object *get_object_struct(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18025 | struct v7_object *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18026 | if (v7_is_null(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18027 | ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18028 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18029 | assert(v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18030 | ret = (struct v7_object *) get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18031 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18032 | if (ret->entity_id_base != V7_ENTITY_ID_PART_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18033 | fprintf(stderr, "not an object!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18034 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18035 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18036 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18038 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18040 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18041 | int v7_is_object(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18042 | return (v & V7_TAG_MASK) == V7_TAG_OBJECT || |
Marko Mikulicic |
0:c0ecb8bf28eb | 18043 | (v & V7_TAG_MASK) == V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18044 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18046 | V7_PRIVATE int v7_is_generic_object(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18047 | return (v & V7_TAG_MASK) == V7_TAG_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18050 | /* Object properties {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18052 | V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18053 | struct v7_property *p = new_property(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18054 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18055 | p->entity_id = V7_ENTITY_ID_PROP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18056 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18057 | p->next = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18058 | p->name = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18059 | p->value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18060 | p->attributes = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18061 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18062 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18064 | V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18065 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18066 | size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18067 | v7_prop_attr_t attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18068 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18069 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18070 | val_t ss; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18071 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18072 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18073 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18074 | if (len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18075 | len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18076 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18078 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18079 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18080 | * len check is needed to allow getting the mbuf from the hidden property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18081 | * TODO(mkm): however hidden properties cannot be safely represented with |
Marko Mikulicic |
0:c0ecb8bf28eb | 18082 | * a zero length string anyway, so this will change. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18083 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18084 | if (o->attributes & V7_OBJ_DENSE_ARRAY && len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18085 | int ok, has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18086 | unsigned long i = cstr_to_ulong(name, len, &ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18087 | if (ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18088 | v7->cur_dense_prop->value = v7_array_get2(v7, obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18089 | return has ? v7->cur_dense_prop : NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18090 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18091 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18092 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18093 | if (len <= 5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18094 | ss = v7_mk_string(v7, name, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18095 | for (p = o->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18096 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18097 | if (p->entity_id != V7_ENTITY_ID_PROP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18098 | fprintf(stderr, "not a prop!=0x%x\n", p->entity_id); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18099 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18101 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18102 | if (p->name == ss && (attrs == 0 || (p->attributes & attrs))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18103 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18104 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18105 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18106 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18107 | for (p = o->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18108 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18109 | const char *s = v7_get_string(v7, &p->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18110 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18111 | if (p->entity_id != V7_ENTITY_ID_PROP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18112 | fprintf(stderr, "not a prop!=0x%x\n", p->entity_id); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18113 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18114 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18115 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18116 | if (n == len && strncmp(s, name, len) == 0 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18117 | (attrs == 0 || (p->attributes & attrs))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18118 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18120 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18121 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18122 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18123 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18125 | V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18126 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18127 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18128 | return v7_get_own_property2(v7, obj, name, len, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18129 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18131 | V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18132 | const char *name, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18133 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18134 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18135 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18136 | for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18137 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18138 | if ((prop = v7_get_own_property(v7, obj, name, len)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18139 | return prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18140 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18142 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18143 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18145 | V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18146 | v7_val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18147 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18148 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18149 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18150 | STATIC char buf[8]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18151 | const char *s = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18152 | uint8_t fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18154 | if (v7_is_string(name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18155 | s = v7_get_string(v7, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18156 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18157 | char *stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18158 | V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18159 | V7_STRINGIFY_DEFAULT, &stmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18160 | s = stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18161 | if (s != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18162 | fr = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18163 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18164 | name_len = strlen(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18165 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18167 | *res = v7_get_property(v7, obj, s, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18169 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18170 | if (fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18171 | free((void *) s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18172 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18173 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18174 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18175 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18176 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18177 | enum v7_err v7_get_throwing(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18178 | size_t name_len, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18179 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18180 | val_t v = obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18182 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18183 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18184 | if (name_len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18185 | name_len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18186 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18187 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18188 | if (v7_is_string(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18189 | v = v7->vals.string_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18190 | } else if (v7_is_number(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18191 | v = v7->vals.number_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18192 | } else if (v7_is_boolean(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18193 | v = v7->vals.boolean_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18194 | } else if (v7_is_undefined(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18195 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 18196 | v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of undefined", |
Marko Mikulicic |
0:c0ecb8bf28eb | 18197 | (int) name_len, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18198 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18199 | } else if (v7_is_null(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18200 | rcode = v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of null", |
Marko Mikulicic |
0:c0ecb8bf28eb | 18201 | (int) name_len, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18202 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18203 | } else if (is_cfunction_lite(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18204 | v = v7->vals.function_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18205 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18207 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18208 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18209 | struct v7_object *o = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18210 | if (v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18211 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18212 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18214 | if (o != NULL && (o->attributes & V7_OBJ_PROXY) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18215 | !is_special_proxy_name(name, name_len)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18216 | /* we need to access the target object through a proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18218 | val_t target_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18219 | val_t handler_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18220 | val_t name_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18221 | val_t get_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18222 | val_t get_args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18223 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18224 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18225 | * we need to create a copy of the name, because the given `name` might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18226 | * be returned by v7_get_string(), and any object creation might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18227 | * invalidate this pointer. Below, we're going to create some objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18228 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 18229 | * It would probably be cleaner to always create a copy before calling |
Marko Mikulicic |
0:c0ecb8bf28eb | 18230 | * v7_get_throwing if the name was returned by v7_get_string(), but that |
Marko Mikulicic |
0:c0ecb8bf28eb | 18231 | * would cause additional pressure on the heap, so let's not do that |
Marko Mikulicic |
0:c0ecb8bf28eb | 18232 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18233 | char *name_copy = (char *) calloc(1, name_len + 1 /* null-term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18234 | memcpy(name_copy, name, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18236 | v7_own(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18237 | v7_own(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18238 | v7_own(v7, &name_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18239 | v7_own(v7, &get_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18240 | v7_own(v7, &get_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18242 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18243 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18244 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18245 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18246 | V7_TRY2(v7_get_throwing(v7, handler_v, "get", ~0, &get_v), clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18248 | if (v7_is_callable(v7, get_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18249 | /* The `get` callback is actually callable, so, use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18251 | /* prepare arguments for the callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18252 | get_args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18253 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18254 | * TODO(dfrank): don't copy string in case we already have val_t (we |
Marko Mikulicic |
0:c0ecb8bf28eb | 18255 | * need some generic function which will take both `const char *` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 18256 | * val_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18257 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18258 | v7_array_set(v7, get_args_v, 0, target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18259 | v7_array_set(v7, get_args_v, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18260 | v7_mk_string(v7, name_copy, name_len, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18262 | /* call `get` callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18263 | V7_TRY2(b_apply(v7, get_v, V7_UNDEFINED, get_args_v, 0, res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18264 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18265 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18266 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18267 | * there's no `get` callback: then, get property from the target object |
Marko Mikulicic |
0:c0ecb8bf28eb | 18268 | * (not from the proxy object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18269 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18270 | V7_TRY2(v7_get_throwing(v7, target_v, name_copy, name_len, res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18271 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18272 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18274 | clean_proxy: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18275 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18276 | free(name_copy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18278 | v7_disown(v7, &get_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18279 | v7_disown(v7, &get_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18280 | v7_disown(v7, &name_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18281 | v7_disown(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18282 | v7_disown(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18283 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18284 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18285 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18286 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18288 | /* regular (non-proxy) property access */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18289 | V7_TRY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18290 | v7_property_value(v7, obj, v7_get_property(v7, v, name, name_len), res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18292 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18293 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18294 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18297 | v7_val_t v7_get(struct v7 *v7, val_t obj, const char *name, size_t name_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18298 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18299 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18300 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18301 | v7_val_t ret = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18303 | rcode = v7_get_throwing(v7, obj, name, name_len, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18304 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18305 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18306 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18307 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18308 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18309 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18310 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18311 | ret = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18314 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18315 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18317 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18318 | V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18319 | v7_val_t name, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18320 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18321 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18322 | STATIC char buf[8]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18323 | const char *s = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18324 | uint8_t fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18325 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18326 | /* subscripting strings */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18327 | if (v7_is_string(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18328 | char ch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18329 | double dch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18331 | rcode = v7_char_code_at(v7, obj, name, &dch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18332 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18333 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18336 | if (!isnan(dch)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18337 | ch = dch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18338 | *res = v7_mk_string(v7, &ch, 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18339 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18340 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18343 | if (v7_is_string(name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18344 | s = v7_get_string(v7, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18345 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18346 | char *stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18347 | V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18348 | V7_STRINGIFY_DEFAULT, &stmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18349 | s = stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18350 | if (s != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18351 | fr = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18352 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18353 | name_len = strlen(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18354 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18355 | V7_TRY(v7_get_throwing(v7, obj, s, name_len, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18357 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18358 | if (fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18359 | free((void *) s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18361 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18362 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18364 | V7_PRIVATE void v7_destroy_property(struct v7_property **p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18365 | *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18366 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18367 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18368 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18369 | V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18370 | val_t obj, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18371 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18372 | val_t setter = prop->value, args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18373 | v7_own(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18374 | args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18375 | v7_own(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18376 | if (prop->attributes & V7_PROPERTY_GETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18377 | setter = v7_array_get(v7, prop->value, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18378 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18379 | v7_array_set(v7, args, 0, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18380 | v7_disown(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18381 | v7_disown(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18382 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18383 | val_t val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18384 | V7_TRY(b_apply(v7, setter, obj, args, 0, &val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18385 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18387 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18388 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18389 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18391 | static v7_prop_attr_t apply_attrs_desc(v7_prop_attr_desc_t attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18392 | v7_prop_attr_t old_attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18393 | v7_prop_attr_t ret = old_attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18394 | if (old_attrs & V7_PROPERTY_NON_CONFIGURABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18395 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18396 | * The property is non-configurable: we can only change it from being |
Marko Mikulicic |
0:c0ecb8bf28eb | 18397 | * writable to non-writable |
Marko Mikulicic |
0:c0ecb8bf28eb | 18398 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18400 | if ((attrs_desc >> _V7_DESC_SHIFT) & V7_PROPERTY_NON_WRITABLE && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18401 | (attrs_desc & V7_PROPERTY_NON_WRITABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18402 | ret |= V7_PROPERTY_NON_WRITABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18403 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18405 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18406 | /* The property is configurable: we can change any attributes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18407 | ret = (old_attrs & ~(attrs_desc >> _V7_DESC_SHIFT)) | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18408 | (attrs_desc & _V7_DESC_MASK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18409 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18411 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18412 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18413 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18414 | int v7_def(struct v7 *v7, val_t obj, const char *name, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18415 | v7_prop_attr_desc_t attrs_desc, v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18416 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18417 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18418 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18419 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18421 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18422 | struct v7_property *tmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18423 | rcode = def_property(v7, obj, name, len, attrs_desc, val, 0 /*not assign*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18424 | &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18425 | ret = (tmp == NULL) ? -1 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18428 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18429 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18430 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18431 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18432 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18433 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18434 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18435 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18436 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18438 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18439 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18441 | int v7_set(struct v7 *v7, val_t obj, const char *name, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18442 | v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18443 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18444 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18445 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18446 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18448 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18449 | struct v7_property *tmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18450 | rcode = set_property(v7, obj, name, len, val, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18451 | ret = (tmp == NULL) ? -1 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18452 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18453 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18454 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18455 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18456 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18457 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18458 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18459 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18461 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18462 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18464 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18465 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18467 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18468 | V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18469 | val_t val, struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18470 | return def_property_v(v7, obj, name, 0, val, 1 /*as_assign*/, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18471 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18473 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18474 | V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18475 | size_t len, v7_val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18476 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18477 | return def_property(v7, obj, name, len, 0, val, 1 /*as_assign*/, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18478 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18480 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18481 | V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18482 | v7_prop_attr_desc_t attrs_desc, val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18483 | uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18484 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18485 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18486 | struct v7_property *prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18487 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18488 | const char *n = v7_get_string(v7, &name, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18490 | v7_own(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18491 | v7_own(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18493 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18494 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18495 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18497 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18498 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18499 | if ((get_object_struct(obj)->attributes & V7_OBJ_PROXY) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18500 | !is_special_proxy_name(n, len)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18501 | /* we need to access the target object through a proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18502 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18503 | val_t target_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18504 | val_t handler_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18505 | val_t set_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18506 | val_t set_args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18508 | v7_own(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18509 | v7_own(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18510 | v7_own(v7, &set_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18511 | v7_own(v7, &set_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18513 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18514 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18515 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18516 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18517 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18518 | * We'll consult "set" property in case of the plain assignment only; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18519 | * Object.defineProperty() has its own trap `defineProperty` which is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 18520 | * yet implemented in v7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 18521 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18522 | if (as_assign) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18523 | V7_TRY2(v7_get_throwing(v7, handler_v, "set", ~0, &set_v), clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18525 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18526 | if (v7_is_callable(v7, set_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18527 | /* The `set` callback is actually callable, so, use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18529 | /* prepare arguments for the callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18530 | set_args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18531 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18532 | * TODO(dfrank): don't copy string in case we already have val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 18533 | * (we need some generic function which will take both const char * and |
Marko Mikulicic |
0:c0ecb8bf28eb | 18534 | * val_t for that) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18535 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18536 | v7_array_set(v7, set_args_v, 0, target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18537 | v7_array_set(v7, set_args_v, 1, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18538 | v7_array_set(v7, set_args_v, 2, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18540 | /* call `set` callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18541 | V7_TRY2(b_apply(v7, set_v, V7_UNDEFINED, set_args_v, 0, &val), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18542 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18544 | /* in strict mode, we should throw if trap returned falsy value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18545 | if (is_strict_mode(v7) && !v7_is_truthy(v7, val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18546 | V7_THROW2( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18547 | v7_throwf(v7, TYPE_ERROR, "Trap returned falsy for property '%s'", |
Marko Mikulicic |
0:c0ecb8bf28eb | 18548 | v7_get_string(v7, &name, NULL)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18549 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18550 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18552 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18553 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18554 | * there's no `set` callback: then, set property on the target object |
Marko Mikulicic |
0:c0ecb8bf28eb | 18555 | * (not on the proxy object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18556 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18557 | V7_TRY2( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18558 | def_property_v(v7, target_v, name, attrs_desc, val, as_assign, res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18559 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18560 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18562 | clean_proxy: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18563 | v7_disown(v7, &set_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18564 | v7_disown(v7, &set_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18565 | v7_disown(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18566 | v7_disown(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18567 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18568 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18569 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18571 | /* regular (non-proxy) property access */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18572 | prop = v7_get_own_property(v7, obj, n, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18573 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18574 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18575 | * The own property with given `name` doesn't exist yet: try to create it, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18576 | * set requested `name` and `attributes`, and append to the object's |
Marko Mikulicic |
0:c0ecb8bf28eb | 18577 | * properties |
Marko Mikulicic |
0:c0ecb8bf28eb | 18578 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18580 | /* make sure the object is extensible */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18581 | if (get_object_struct(obj)->attributes & V7_OBJ_NOT_EXTENSIBLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18582 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18583 | * We should throw if we use `Object.defineProperty`, or if we're in |
Marko Mikulicic |
0:c0ecb8bf28eb | 18584 | * strict mode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18585 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18586 | if (is_strict_mode(v7) || !as_assign) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18587 | V7_THROW(v7_throwf(v7, TYPE_ERROR, "Object is not extensible")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18588 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18589 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18590 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18593 | if ((prop = v7_mk_property(v7)) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18594 | prop = NULL; /* LCOV_EXCL_LINE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18595 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18596 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18597 | prop->name = name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18598 | prop->value = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18599 | prop->attributes = apply_attrs_desc(attrs_desc, V7_DEFAULT_PROPERTY_ATTRS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18601 | prop->next = get_object_struct(obj)->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18602 | get_object_struct(obj)->properties = prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18603 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18604 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18605 | /* Property already exists */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18606 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18607 | if (prop->attributes & V7_PROPERTY_NON_WRITABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18608 | /* The property is read-only */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18610 | if (as_assign) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18611 | /* Plain assignment: in strict mode throw, otherwise ignore */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18612 | if (is_strict_mode(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18613 | V7_THROW( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18614 | v7_throwf(v7, TYPE_ERROR, "Cannot assign to read-only property")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18615 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18616 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18617 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18618 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18619 | } else if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18620 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18621 | * Use `Object.defineProperty` semantic, and the property is |
Marko Mikulicic |
0:c0ecb8bf28eb | 18622 | * non-configurable: if no value is provided, or if new value is equal |
Marko Mikulicic |
0:c0ecb8bf28eb | 18623 | * to the existing one, then just fall through to change attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18624 | * otherwise, throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18625 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18627 | if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18628 | uint8_t equal = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18629 | if (v7_is_string(val) && v7_is_string(prop->value)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18630 | equal = (s_cmp(v7, val, prop->value) == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18631 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18632 | equal = (val == prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18633 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18634 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18635 | if (!equal) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18636 | /* Values are not equal: should throw */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18637 | V7_THROW(v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18638 | "Cannot redefine read-only property")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18639 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18640 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18641 | * Values are equal. Will fall through so that attributes might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18642 | * change. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18643 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18644 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18645 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18646 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18647 | * No value is provided. Will fall through so that attributes might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18648 | * change. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18649 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18650 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18651 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18652 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18653 | * Use `Object.defineProperty` semantic, and the property is |
Marko Mikulicic |
0:c0ecb8bf28eb | 18654 | * configurable: will fall through and assign new value, effectively |
Marko Mikulicic |
0:c0ecb8bf28eb | 18655 | * ignoring non-writable flag. This is the same as making a property |
Marko Mikulicic |
0:c0ecb8bf28eb | 18656 | * writable, then assigning a new value, and making a property |
Marko Mikulicic |
0:c0ecb8bf28eb | 18657 | * non-writable again. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18658 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18659 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18660 | } else if (prop->attributes & V7_PROPERTY_SETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18661 | /* Invoke setter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18662 | V7_TRY(v7_invoke_setter(v7, prop, obj, val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18663 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18664 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18665 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18667 | /* Set value and apply attrs delta */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18668 | if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18669 | prop->value = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18670 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18671 | prop->attributes = apply_attrs_desc(attrs_desc, prop->attributes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18672 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18674 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18675 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18676 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18677 | *res = prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18678 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18680 | v7_disown(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18681 | v7_disown(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18683 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18686 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18687 | V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18688 | size_t len, v7_prop_attr_desc_t attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18689 | v7_val_t val, uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18690 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18691 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18692 | val_t name_val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18694 | v7_own(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18695 | v7_own(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18696 | v7_own(v7, &name_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18697 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18698 | if (len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18699 | len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18700 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18702 | name_val = v7_mk_string(v7, name, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18703 | V7_TRY(def_property_v(v7, obj, name_val, attrs_desc, val, as_assign, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18704 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18705 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18706 | v7_disown(v7, &name_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18707 | v7_disown(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18708 | v7_disown(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18710 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18711 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18713 | V7_PRIVATE int set_method(struct v7 *v7, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18714 | v7_cfunction_t *func, int num_args) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18715 | return v7_def(v7, obj, name, strlen(name), V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18716 | mk_cfunction_obj(v7, func, num_args)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18717 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18719 | int v7_set_method(struct v7 *v7, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18720 | v7_cfunction_t *func) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18721 | return set_method(v7, obj, name, func, ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18722 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18723 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18724 | V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18725 | v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18726 | return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18727 | v7_mk_cfunction(f)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18728 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18730 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18731 | * See comments in `object_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 18732 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18733 | int v7_del(struct v7 *v7, val_t obj, const char *name, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18734 | struct v7_property *prop, *prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18736 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18737 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18738 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18739 | if (len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18740 | len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18741 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18742 | for (prev = NULL, prop = get_object_struct(obj)->properties; prop != NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18743 | prev = prop, prop = prop->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18744 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18745 | const char *s = v7_get_string(v7, &prop->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18746 | if (n == len && strncmp(s, name, len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18747 | if (prev) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18748 | prev->next = prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18749 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18750 | get_object_struct(obj)->properties = prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18751 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18752 | v7_destroy_property(&prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18753 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18754 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18755 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18756 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18757 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18758 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18759 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18760 | V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18761 | struct v7_property *p, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18762 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18763 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18764 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18765 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18767 | if (p->attributes & V7_PROPERTY_GETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18768 | val_t getter = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18769 | if (p->attributes & V7_PROPERTY_SETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18770 | getter = v7_array_get(v7, p->value, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18771 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18772 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18773 | V7_TRY(b_apply(v7, getter, obj, V7_UNDEFINED, 0, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18774 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18775 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18776 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18778 | *res = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18779 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18780 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18781 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18782 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18783 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18785 | enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18786 | struct prop_iter_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18787 | return init_prop_iter_ctx(v7, obj, 1 /*proxy-transparent*/, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18788 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18789 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18790 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18791 | V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18792 | int proxy_transp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18793 | struct prop_iter_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18794 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18796 | v7_own(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18798 | memset(ctx, 0x00, sizeof(*ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18799 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18800 | if (v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18801 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18802 | if (proxy_transp && get_object_struct(obj)->attributes & V7_OBJ_PROXY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18803 | v7_val_t ownKeys_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18804 | v7_val_t args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18805 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18806 | v7_own(v7, &ownKeys_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18807 | v7_own(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18809 | ctx->proxy_ctx = |
Marko Mikulicic |
0:c0ecb8bf28eb | 18810 | (struct prop_iter_proxy_ctx *) calloc(1, sizeof(*ctx->proxy_ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18812 | ctx->proxy_ctx->target_obj = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18813 | ctx->proxy_ctx->handler_obj = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18814 | ctx->proxy_ctx->own_keys = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18815 | ctx->proxy_ctx->get_own_prop_desc = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18817 | v7_own(v7, &ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18818 | v7_own(v7, &ctx->proxy_ctx->handler_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18819 | v7_own(v7, &ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18820 | v7_own(v7, &ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18821 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18822 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18823 | &ctx->proxy_ctx->target_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18824 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18825 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18826 | &ctx->proxy_ctx->handler_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18827 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18829 | V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "ownKeys", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18830 | &ownKeys_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18831 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18832 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18833 | if (v7_is_callable(v7, ownKeys_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18834 | /* prepare arguments for the ownKeys callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18835 | args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18836 | v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18837 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18838 | /* call `ownKeys` callback, and save the result in context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18839 | V7_TRY2(b_apply(v7, ownKeys_v, V7_UNDEFINED, args_v, 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18840 | &ctx->proxy_ctx->own_keys), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18841 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18843 | ctx->proxy_ctx->has_own_keys = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18844 | ctx->proxy_ctx->own_key_idx = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18846 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18847 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18848 | * No ownKeys callback, so we'll iterate real properties of the target |
Marko Mikulicic |
0:c0ecb8bf28eb | 18849 | * object |
Marko Mikulicic |
0:c0ecb8bf28eb | 18850 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18852 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18853 | * TODO(dfrank): add support for the target object which is a proxy as |
Marko Mikulicic |
0:c0ecb8bf28eb | 18854 | * well |
Marko Mikulicic |
0:c0ecb8bf28eb | 18855 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18856 | ctx->cur_prop = |
Marko Mikulicic |
0:c0ecb8bf28eb | 18857 | get_object_struct(ctx->proxy_ctx->target_obj)->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18859 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18860 | V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "_gpdc", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18861 | &ctx->proxy_ctx->get_own_prop_desc), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18862 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18863 | if (v7_is_foreign(ctx->proxy_ctx->get_own_prop_desc)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18864 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18865 | * C callback for getting property descriptor is provided: will use it |
Marko Mikulicic |
0:c0ecb8bf28eb | 18866 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18867 | ctx->proxy_ctx->has_get_own_prop_desc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18868 | ctx->proxy_ctx->has_get_own_prop_desc_C = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18869 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18870 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18871 | * No C callback for getting property descriptor is provided, let's |
Marko Mikulicic |
0:c0ecb8bf28eb | 18872 | * check if there is a JS one.. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18873 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18874 | V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18875 | "getOwnPropertyDescriptor", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18876 | &ctx->proxy_ctx->get_own_prop_desc), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18877 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18879 | if (v7_is_callable(v7, ctx->proxy_ctx->get_own_prop_desc)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18880 | /* Yes there is, we'll use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18881 | ctx->proxy_ctx->has_get_own_prop_desc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18882 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18883 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18885 | clean_proxy: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18886 | v7_disown(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18887 | v7_disown(v7, &ownKeys_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18889 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18890 | /* something went wrong, so, disown values in the context and free it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18891 | v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18892 | v7_disown(v7, &ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18893 | v7_disown(v7, &ctx->proxy_ctx->handler_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18894 | v7_disown(v7, &ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18895 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18896 | free(ctx->proxy_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18897 | ctx->proxy_ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18899 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18900 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18901 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18902 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 18903 | (void) proxy_transp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18904 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18906 | /* Object is not a proxy: we'll iterate real properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18907 | ctx->cur_prop = get_object_struct(obj)->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18909 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18911 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18912 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18913 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18914 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18915 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18916 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18917 | v7_disown(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18918 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18919 | ctx->init = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18921 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18924 | void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18925 | if (ctx->init) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18926 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18927 | if (ctx->proxy_ctx != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18928 | v7_disown(v7, &ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18929 | v7_disown(v7, &ctx->proxy_ctx->handler_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18930 | v7_disown(v7, &ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18931 | v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18932 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18933 | free(ctx->proxy_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18934 | ctx->proxy_ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18935 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 18936 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18937 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18938 | ctx->init = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18939 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18940 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18942 | int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18943 | v7_val_t *value, v7_prop_attr_t *attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18944 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18945 | if (next_prop(v7, ctx, name, value, attrs, &ok) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18946 | fprintf(stderr, "next_prop failed\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18947 | ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18948 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18949 | return ok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18950 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18952 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18953 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18954 | static enum v7_err get_custom_prop_desc(struct v7 *v7, v7_val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18955 | struct prop_iter_ctx *ctx, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18956 | struct v7_property *res_prop, int *ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18957 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18959 | v7_val_t args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18960 | v7_val_t desc_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18961 | v7_val_t tmpflag_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18963 | v7_own(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18964 | v7_own(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18965 | v7_own(v7, &desc_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18966 | v7_own(v7, &tmpflag_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18968 | *ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18970 | if (ctx->proxy_ctx->has_get_own_prop_desc_C) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18971 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18972 | * There is a C callback which should fill the property descriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 18973 | * structure, see `v7_get_own_prop_desc_cb_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 18974 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18975 | v7_get_own_prop_desc_cb_t *cb = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18976 | memset(res_prop, 0, sizeof(*res_prop)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18977 | cb = (v7_get_own_prop_desc_cb_t *) v7_get_ptr( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18978 | v7, ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18980 | res_prop->attributes = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18981 | res_prop->value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18983 | *ok = !!cb(v7, ctx->proxy_ctx->target_obj, name, &res_prop->attributes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18984 | &res_prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18985 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18986 | /* prepare arguments for the getOwnPropertyDescriptor callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18987 | args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18988 | v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18989 | v7_array_set(v7, args_v, 1, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18991 | /* call getOwnPropertyDescriptor callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18992 | V7_TRY(b_apply(v7, ctx->proxy_ctx->get_own_prop_desc, V7_UNDEFINED, args_v, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18993 | 0, &desc_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18995 | if (v7_is_object(desc_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18996 | res_prop->attributes = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18998 | V7_TRY(v7_get_throwing(v7, desc_v, "writable", ~0, &tmpflag_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18999 | if (!v7_is_truthy(v7, tmpflag_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19000 | res_prop->attributes |= V7_PROPERTY_NON_WRITABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19001 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19003 | V7_TRY(v7_get_throwing(v7, desc_v, "configurable", ~0, &tmpflag_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19004 | if (!v7_is_truthy(v7, tmpflag_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19005 | res_prop->attributes |= V7_PROPERTY_NON_CONFIGURABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19008 | V7_TRY(v7_get_throwing(v7, desc_v, "enumerable", ~0, &tmpflag_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19009 | if (!v7_is_truthy(v7, tmpflag_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19010 | res_prop->attributes |= V7_PROPERTY_NON_ENUMERABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19011 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19013 | V7_TRY(v7_get_throwing(v7, desc_v, "value", ~0, &res_prop->value)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19015 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19016 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19017 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19018 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19019 | /* We always set the name in the property descriptor to the actual name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19020 | res_prop->name = name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19021 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19022 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19023 | v7_disown(v7, &tmpflag_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19024 | v7_disown(v7, &desc_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19025 | v7_disown(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19026 | v7_disown(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19027 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19028 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19029 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19030 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19031 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19032 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19033 | V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19034 | v7_val_t *name, v7_val_t *value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19035 | v7_prop_attr_t *attrs, int *ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19036 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19037 | struct v7_property p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19039 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19040 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19041 | memset(&p, 0, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19042 | p.name = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19043 | p.value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19045 | v7_own(v7, &p.name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19046 | v7_own(v7, &p.value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19047 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19048 | assert(ctx->init); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19050 | *ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19052 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 19053 | if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_own_keys) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19054 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19055 | * No `ownKeys` callback, so we'll iterate real properties of the object |
Marko Mikulicic |
0:c0ecb8bf28eb | 19056 | * (either the given object or, if it's a proxy, the proxy's target object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19057 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19059 | if (ctx->cur_prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19060 | if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_get_own_prop_desc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19061 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19062 | * There is no `getOwnPropertyDescriptor` callback, so, use the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 19063 | * real property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19064 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19065 | memcpy(&p, ctx->cur_prop, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19066 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19067 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19068 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19069 | * There is a `getOwnPropertyDescriptor` callback, so call it for the |
Marko Mikulicic |
0:c0ecb8bf28eb | 19070 | * name of the current real property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19071 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19072 | V7_TRY(get_custom_prop_desc(v7, ctx->cur_prop->name, ctx, &p, ok)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19073 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19074 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19075 | ctx->cur_prop = ctx->cur_prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19076 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19077 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19078 | /* We have custom own keys */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19079 | v7_val_t cur_key = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19080 | size_t len = v7_array_length(v7, ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19081 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19082 | v7_own(v7, &cur_key); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19084 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19085 | * Iterate through the custom own keys until we can get the proper property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19086 | * descriptor for the given key |
Marko Mikulicic |
0:c0ecb8bf28eb | 19087 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19088 | while (!*ok && (size_t) ctx->proxy_ctx->own_key_idx < len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19089 | cur_key = v7_array_get(v7, ctx->proxy_ctx->own_keys, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19090 | ctx->proxy_ctx->own_key_idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19091 | ctx->proxy_ctx->own_key_idx++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19092 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19093 | if (ctx->proxy_ctx->has_get_own_prop_desc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19094 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19095 | * There is a `getOwnPropertyDescriptor` callback, so, call it for the |
Marko Mikulicic |
0:c0ecb8bf28eb | 19096 | * current custom key and get all descriptor data from the object |
Marko Mikulicic |
0:c0ecb8bf28eb | 19097 | * returned. The `ok` variable will be updated appropriately (it will |
Marko Mikulicic |
0:c0ecb8bf28eb | 19098 | * be 0 if the callback did not return a proper descriptor) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19099 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19100 | V7_TRY2(get_custom_prop_desc(v7, cur_key, ctx, &p, ok), clean_custom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19101 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19102 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19103 | * There is no `getOwnPropertyDescriptor` callback, so, try to get |
Marko Mikulicic |
0:c0ecb8bf28eb | 19104 | * real property with the name equal to the current key |
Marko Mikulicic |
0:c0ecb8bf28eb | 19105 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19106 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19107 | const char *name = v7_get_string(v7, &cur_key, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19109 | struct v7_property *real_prop = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19110 | v7_get_own_property(v7, ctx->proxy_ctx->target_obj, name, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19111 | if (real_prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19112 | /* Property exists, so use data from its descriptor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19113 | memcpy(&p, real_prop, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19114 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19115 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19116 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19117 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19118 | clean_custom: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19119 | v7_disown(v7, &cur_key); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19120 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19121 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19122 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19123 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19125 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 19126 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19127 | * Proxy is disabled: just get the next property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19128 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19129 | if (ctx->cur_prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19130 | memcpy(&p, ctx->cur_prop, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19131 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19132 | ctx->cur_prop = ctx->cur_prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19133 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19134 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19135 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19136 | /* If we have a valid property descriptor, use data from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19137 | if (*ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19138 | if (name != NULL) *name = p.name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19139 | if (value != NULL) *value = p.value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19140 | if (attrs != NULL) *attrs = p.attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19143 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 19144 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19145 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19146 | v7_disown(v7, &p.value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19147 | v7_disown(v7, &p.name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19148 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19149 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19151 | /* }}} Object properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19153 | /* Object prototypes {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19154 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19155 | V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19156 | struct v7_object *proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19157 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19158 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19160 | if (obj->attributes & V7_OBJ_FUNCTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19161 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19162 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19163 | ((struct v7_generic_object *) obj)->prototype = proto; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19164 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19165 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19167 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19168 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19170 | V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19171 | struct v7_object *obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19172 | if (obj->attributes & V7_OBJ_FUNCTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19173 | return get_object_struct(v7->vals.function_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19174 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19175 | return ((struct v7_generic_object *) obj)->prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19176 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19177 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19178 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19179 | V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19180 | if (!v7_is_object(o) || !v7_is_object(p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19181 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19182 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19183 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19184 | /* walk the prototype chain */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19185 | for (; !v7_is_null(o); o = v7_get_proto(v7, o)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19186 | if (v7_get_proto(v7, o) == p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19187 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19188 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19189 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19190 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19191 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19192 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19193 | int v7_is_instanceof(struct v7 *v7, val_t o, const char *c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19194 | return v7_is_instanceof_v(v7, o, v7_get(v7, v7->vals.global_object, c, ~0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19197 | int v7_is_instanceof_v(struct v7 *v7, val_t o, val_t c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19198 | return is_prototype_of(v7, o, v7_get(v7, c, "prototype", 9)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19199 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19201 | v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19202 | if (v7_is_generic_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19203 | v7_val_t old_proto = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19204 | v7_object_to_value(obj_prototype(v7, get_object_struct(obj))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19205 | obj_prototype_set(v7, get_object_struct(obj), get_object_struct(proto)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19206 | return old_proto; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19207 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19208 | return V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19209 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19210 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19212 | val_t v7_get_proto(struct v7 *v7, val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19213 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19214 | * NOTE: we don't use v7_is_callable() here, because it involves walking |
Marko Mikulicic |
0:c0ecb8bf28eb | 19215 | * through the object's properties, which may be expensive. And it's done |
Marko Mikulicic |
0:c0ecb8bf28eb | 19216 | * anyway for cfunction objects as it would for any other generic objects by |
Marko Mikulicic |
0:c0ecb8bf28eb | 19217 | * the call to `obj_prototype()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19218 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 19219 | * Since this function is called quite often (at least, GC walks the |
Marko Mikulicic |
0:c0ecb8bf28eb | 19220 | * prototype chain), it's better to just handle cfunction objects as generic |
Marko Mikulicic |
0:c0ecb8bf28eb | 19221 | * objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19222 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19223 | if (is_js_function(obj) || is_cfunction_lite(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19224 | return v7->vals.function_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19225 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19226 | return v7_object_to_value(obj_prototype(v7, get_object_struct(obj))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19227 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19229 | V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19230 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19231 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19232 | if (!v7_is_object(obj)) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19233 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19234 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19235 | for (p = o->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19236 | if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19237 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19238 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19239 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19240 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19241 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19242 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19244 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19245 | * Returns the user data property structure associated with obj, or NULL if |
Marko Mikulicic |
0:c0ecb8bf28eb | 19246 | * `obj` is not an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19247 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19248 | static struct v7_property *get_or_create_user_data_property(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19249 | v7_val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19250 | struct v7_property *p = get_user_data_property(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19251 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19253 | if (p != NULL) return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19255 | if (!v7_is_object(obj)) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19256 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19257 | v7_own(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19258 | p = v7_mk_property(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19259 | v7_disown(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19261 | p->attributes |= _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR | _V7_PROPERTY_HIDDEN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19263 | p->next = o->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19264 | o->properties = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19265 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19266 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19267 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19268 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19269 | void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19270 | struct v7_property *p = get_or_create_user_data_property(v7, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19271 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19272 | p->value = v7_mk_foreign(v7, ud); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19273 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19275 | void *v7_get_user_data(struct v7 *v7, v7_val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19276 | struct v7_property *p = get_user_data_property(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19277 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19278 | if (p == NULL) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19279 | return v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19280 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19282 | void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19283 | struct v7_property *p = get_or_create_user_data_property(v7, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19284 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19285 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19286 | void *v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19287 | v7_destructor_cb_t *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19288 | } fu; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19290 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19292 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19293 | if (d != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19294 | o->attributes |= V7_OBJ_HAS_DESTRUCTOR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19295 | fu.f = d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19296 | p->name = v7_mk_foreign(v7, fu.v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19297 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19298 | o->attributes &= ~V7_OBJ_HAS_DESTRUCTOR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19299 | p->name = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19303 | /* }}} Object prototypes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19304 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 19305 | #line 1 "v7/src/regexp.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 19306 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19307 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19308 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 19309 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 19310 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19312 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19313 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19314 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19315 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19316 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19317 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19318 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19319 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19321 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 19322 | enum v7_err v7_mk_regexp(struct v7 *v7, const char *re, size_t re_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19323 | const char *flags, size_t flags_len, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19324 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19325 | struct slre_prog *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19326 | struct v7_regexp *rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19328 | if (re_len == ~((size_t) 0)) re_len = strlen(re); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19330 | if (slre_compile(re, re_len, flags, flags_len, &p, 1) != SLRE_OK || |
Marko Mikulicic |
0:c0ecb8bf28eb | 19331 | p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19332 | rcode = v7_throwf(v7, TYPE_ERROR, "Invalid regex"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19333 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19334 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19335 | *res = mk_object(v7, v7->vals.regexp_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19336 | rp = (struct v7_regexp *) malloc(sizeof(*rp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19337 | rp->regexp_string = v7_mk_string(v7, re, re_len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19338 | v7_own(v7, &rp->regexp_string); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19339 | rp->compiled_regexp = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19340 | rp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19342 | v7_def(v7, *res, "", 0, _V7_DESC_HIDDEN(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 19343 | pointer_to_value(rp) | V7_TAG_REGEXP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19346 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19347 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19348 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19350 | V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19351 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19352 | int is = v7_is_regexp(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19353 | (void) is; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19354 | assert(is == 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19355 | /* TODO(mkm): make regexp use user data API */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19356 | p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19357 | assert(p != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19358 | return (struct v7_regexp *) get_ptr(p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19361 | int v7_is_regexp(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19362 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19363 | if (!v7_is_generic_object(v)) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19364 | /* TODO(mkm): make regexp use user data API */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19365 | p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19366 | if (p == NULL) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19367 | return (p->value & V7_TAG_MASK) == V7_TAG_REGEXP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19368 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19370 | V7_PRIVATE size_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 19371 | get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19372 | int re_flags = slre_get_flags(rp->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19373 | size_t n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19375 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19376 | if (re_flags & SLRE_FLAG_G) buf[n++] = 'g'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19377 | if (re_flags & SLRE_FLAG_I) buf[n++] = 'i'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19378 | if (re_flags & SLRE_FLAG_M) buf[n++] = 'm'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19380 | assert(n <= _V7_REGEXP_MAX_FLAGS_LEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19381 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19382 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19383 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19385 | #else /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19387 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19388 | * Dummy implementation when RegExp support is disabled: just return 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 19389 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19390 | int v7_is_regexp(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19391 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19392 | (void) v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19393 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19394 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19396 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19397 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 19398 | #line 1 "v7/src/exceptions.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 19399 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19400 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19401 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 19402 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 19403 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19405 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19406 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19407 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19408 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19409 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19410 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19411 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19413 | enum v7_err v7_throw(struct v7 *v7, v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19414 | v7->vals.thrown_error = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19415 | v7->is_thrown = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19416 | return V7_EXEC_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19417 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19419 | void v7_clear_thrown_value(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19420 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19421 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19422 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19424 | enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19425 | ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19426 | /* TODO(dfrank) : get rid of v7->error_msg, allocate mem right here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19427 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19428 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19429 | val_t e = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19430 | va_start(ap, err_fmt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19431 | c_vsnprintf(v7->error_msg, sizeof(v7->error_msg), err_fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19432 | va_end(ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19434 | v7_own(v7, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19435 | rcode = create_exception(v7, typ, v7->error_msg, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19436 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19437 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19438 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19440 | rcode = v7_throw(v7, e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19442 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19443 | v7_disown(v7, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19444 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19445 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19446 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19447 | enum v7_err v7_rethrow(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19448 | assert(v7->is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19449 | #ifdef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 19450 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19451 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19452 | return V7_EXEC_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19453 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19455 | v7_val_t v7_get_thrown_value(struct v7 *v7, uint8_t *is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19456 | if (is_thrown != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19457 | *is_thrown = v7->is_thrown; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19458 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19459 | return v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19462 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19463 | * Create an instance of the exception with type `typ` (see `TYPE_ERROR`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19464 | * `SYNTAX_ERROR`, etc) and message `msg`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19465 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19466 | V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19467 | const char *msg, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19468 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19469 | uint8_t saved_creating_exception = v7->creating_exception; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19470 | val_t ctor_args = V7_UNDEFINED, ctor_func = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19471 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 19472 | assert(v7_is_undefined(v7->vals.thrown_error)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19473 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19475 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19477 | v7_own(v7, &ctor_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19478 | v7_own(v7, &ctor_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19480 | if (v7->creating_exception) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19481 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 19482 | fprintf(stderr, "Exception creation throws an exception %s: %s\n", typ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19483 | msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19484 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19485 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19486 | v7->creating_exception = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19488 | /* Prepare arguments for the `Error` constructor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19489 | ctor_args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19490 | v7_array_set(v7, ctor_args, 0, v7_mk_string(v7, msg, strlen(msg), 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19492 | /* Get constructor for the given error `typ` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19493 | ctor_func = v7_get(v7, v7->vals.global_object, typ, ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19494 | if (v7_is_undefined(ctor_func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19495 | fprintf(stderr, "cannot find exception %s\n", typ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19497 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19498 | /* Create an error object, with prototype from constructor function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19499 | *res = mk_object(v7, v7_get(v7, ctor_func, "prototype", 9)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19500 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19501 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19502 | * Finally, call the error constructor, passing an error object as `this` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19503 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19504 | V7_TRY(b_apply(v7, ctor_func, *res, ctor_args, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19505 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19507 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19508 | v7->creating_exception = saved_creating_exception; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19510 | v7_disown(v7, &ctor_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19511 | v7_disown(v7, &ctor_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19513 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19514 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19515 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 19516 | #line 1 "v7/src/conversion.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 19517 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19518 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19519 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 19520 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 19521 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19523 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19524 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19525 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19526 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19527 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19528 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19529 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19530 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19531 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19532 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19533 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19534 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19535 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19536 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19538 | static void save_val(struct v7 *v7, const char *str, size_t str_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19539 | val_t *dst_v, char *dst, size_t dst_size, int wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19540 | size_t *res_wanted_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19541 | if (dst_v != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19542 | *dst_v = v7_mk_string(v7, str, str_len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19544 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19545 | if (dst != NULL && dst_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19546 | size_t size = str_len + 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19547 | if (size > dst_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19548 | size = dst_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19549 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19550 | memcpy(dst, str, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19552 | /* make sure we have null-term */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19553 | dst[dst_size - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19554 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19556 | if (res_wanted_len != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19557 | *res_wanted_len = (wanted_len >= 0) ? (size_t) wanted_len : str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19558 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19559 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19561 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19562 | V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19563 | char *buf, size_t buf_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19564 | size_t *res_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19565 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19566 | char tmp_buf[25]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19567 | double num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19568 | size_t wanted_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19570 | assert(!v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19572 | memset(tmp_buf, 0x00, sizeof(tmp_buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19574 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19576 | switch (val_type(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19577 | case V7_TYPE_STRING: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19578 | /* if `res` provided, set it to source value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19579 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19580 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19581 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19582 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19583 | /* if buf provided, copy string data there */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19584 | if (buf != NULL && buf_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19585 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19586 | const char *str = v7_get_string(v7, &v, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19587 | size += 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19589 | if (size > buf_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19590 | size = buf_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19593 | memcpy(buf, str, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19594 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19595 | /* make sure we have a null-term */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19596 | buf[buf_size - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19597 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19599 | if (res_len != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19600 | v7_get_string(v7, &v, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19601 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19603 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19604 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19605 | case V7_TYPE_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19606 | strncpy(tmp_buf, "null", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19607 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19608 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19609 | case V7_TYPE_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19610 | strncpy(tmp_buf, "undefined", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19611 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19612 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19613 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19614 | if (v7_get_bool(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19615 | strncpy(tmp_buf, "true", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19616 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19617 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19618 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19619 | strncpy(tmp_buf, "false", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19620 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19621 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19623 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19624 | if (v == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19625 | strncpy(tmp_buf, "NaN", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19626 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19627 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19628 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19629 | num = v7_get_double(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19630 | if (isinf(num)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19631 | if (num < 0.0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19632 | strncpy(tmp_buf, "-Infinity", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19633 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19634 | strncpy(tmp_buf, "Infinity", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19636 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19637 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19638 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19639 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19640 | const char *fmt = num > 1e10 ? "%.21g" : "%.10g"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19641 | wanted_len = snprintf(tmp_buf, sizeof(tmp_buf), fmt, num); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19642 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19643 | res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19644 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19645 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19646 | case V7_TYPE_CFUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19647 | #ifdef V7_UNIT_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 19648 | wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_xxxxxx"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19649 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19650 | res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19651 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19652 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 19653 | wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_%p", get_ptr(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19654 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19655 | res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19656 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19657 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19658 | case V7_TYPE_FOREIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19659 | wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "[foreign_%p]", |
Marko Mikulicic |
0:c0ecb8bf28eb | 19660 | v7_get_ptr(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19661 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19662 | res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19663 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19664 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19665 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19666 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19668 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19670 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19671 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19672 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19674 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19675 | V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19676 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19678 | assert(!v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19680 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19682 | if (v7_is_number(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19683 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19686 | if (v7_is_undefined(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19687 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19688 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19689 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19690 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19691 | if (v7_is_null(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19692 | *res = v7_mk_number(v7, 0.0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19693 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19694 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19696 | if (v7_is_boolean(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19697 | *res = v7_mk_number(v7, !!v7_get_bool(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19698 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19701 | if (is_cfunction_lite(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19702 | *res = v7_mk_number(v7, 0.0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19703 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19704 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19706 | if (v7_is_string(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19707 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19708 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19709 | char *e, *s = (char *) v7_get_string(v7, res, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19710 | if (n != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19711 | d = cs_strtod(s, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19712 | if (e - n != s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19713 | d = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19714 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19715 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19716 | /* empty string: convert to 0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19717 | d = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19718 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19719 | *res = v7_mk_number(v7, d); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19720 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19721 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19723 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19725 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19726 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19727 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19729 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19730 | enum v7_err to_primitive(struct v7 *v7, val_t v, enum to_primitive_hint hint, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19731 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19732 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19733 | enum v7_err (*p_func)(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19735 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19736 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19737 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19739 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19740 | * If given value is an object, try to convert it to string by calling first |
Marko Mikulicic |
0:c0ecb8bf28eb | 19741 | * preferred function (`toString()` or `valueOf()`, depending on the `hint` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19742 | * argument) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19743 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19744 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19745 | /* Handle special case for Date object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19746 | if (hint == V7_TO_PRIMITIVE_HINT_AUTO) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19747 | hint = (v7_get_proto(v7, *res) == v7->vals.date_prototype) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19748 | ? V7_TO_PRIMITIVE_HINT_STRING |
Marko Mikulicic |
0:c0ecb8bf28eb | 19749 | : V7_TO_PRIMITIVE_HINT_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19750 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19751 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19752 | p_func = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19753 | (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_value_of : obj_to_string; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19754 | rcode = p_func(v7, *res, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19755 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19756 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19757 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19758 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19759 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19760 | * If returned value is still an object, get original argument value |
Marko Mikulicic |
0:c0ecb8bf28eb | 19761 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19762 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19763 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19764 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19765 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19767 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19768 | * If the value is still an object, try to call second function (`valueOf()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19769 | * or `toString()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19770 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19771 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19772 | p_func = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19773 | (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_to_string : obj_value_of; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19774 | rcode = p_func(v7, *res, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19775 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19776 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19777 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19778 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19780 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19781 | * If the value is still an object, then throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19782 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19783 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19784 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19785 | v7_throwf(v7, TYPE_ERROR, "Cannot convert object to primitive value"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19786 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19789 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19790 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19791 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19792 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19794 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19795 | V7_PRIVATE enum v7_err to_string(struct v7 *v7, val_t v, val_t *res, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19796 | size_t buf_size, size_t *res_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19797 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19799 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19800 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19801 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19802 | * Convert value to primitive if needed, calling `toString()` first |
Marko Mikulicic |
0:c0ecb8bf28eb | 19803 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19804 | V7_TRY(to_primitive(v7, v, V7_TO_PRIMITIVE_HINT_STRING, &v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19805 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19806 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19807 | * Now, we're guaranteed to have a primitive here. Convert it to string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19808 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19809 | V7_TRY(primitive_to_str(v7, v, res, buf, buf_size, res_len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19811 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19812 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19813 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19816 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19817 | V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19818 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19820 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19821 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19822 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19823 | * Convert value to primitive if needed, calling `valueOf()` first |
Marko Mikulicic |
0:c0ecb8bf28eb | 19824 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19825 | rcode = to_primitive(v7, *res, V7_TO_PRIMITIVE_HINT_NUMBER, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19826 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19827 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19828 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19830 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19831 | * Now, we're guaranteed to have a primitive here. Convert it to number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19832 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19833 | rcode = primitive_to_number(v7, *res, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19834 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19835 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19836 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19837 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19838 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19839 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19840 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19842 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19843 | V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19844 | long *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19845 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19846 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19848 | /* if value is `undefined`, just return `default_value` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19849 | if (v7_is_undefined(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19850 | *res = default_value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19851 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19852 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19854 | /* Try to convert value to number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19855 | rcode = to_number_v(v7, v, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19856 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19857 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19859 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19860 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19861 | * Conversion to number succeeded, so, convert it to long |
Marko Mikulicic |
0:c0ecb8bf28eb | 19862 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19863 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19864 | d = v7_get_double(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19865 | /* We want to return LONG_MAX if d is positive Inf, thus d < 0 check */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19866 | if (isnan(d) || (isinf(d) && d < 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19867 | *res = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19868 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19869 | } else if (d > LONG_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19870 | *res = LONG_MAX; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19871 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19872 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19873 | *res = (long) d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19874 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19875 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19876 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19877 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19878 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19880 | V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19881 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19882 | val_t func_valueOf = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19884 | v7_own(v7, &func_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19885 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19887 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19888 | * TODO(dfrank): use `assert(v7_is_object(v))` instead, like `obj_to_string()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19889 | * does, and fix all callers to ensure it's an object before calling. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19890 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 19891 | * Or, conversely, make `obj_to_string()` to accept objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19892 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19893 | if (!v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19894 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19895 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19898 | V7_TRY(v7_get_throwing(v7, v, "valueOf", 7, &func_valueOf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19899 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19900 | if (v7_is_callable(v7, func_valueOf)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19901 | V7_TRY(b_apply(v7, func_valueOf, v, V7_UNDEFINED, 0, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19902 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19904 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19905 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19906 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19907 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19909 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19910 | v7_disown(v7, &func_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19912 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19913 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19915 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19916 | * Caller should ensure that `v` is an object |
Marko Mikulicic |
0:c0ecb8bf28eb | 19917 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19918 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19919 | V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19920 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19921 | val_t to_string_func = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19923 | /* Caller should ensure that `v` is an object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19924 | assert(v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19926 | v7_own(v7, &to_string_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19927 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19929 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19930 | * If `toString` is callable, then call it; otherwise, just return source |
Marko Mikulicic |
0:c0ecb8bf28eb | 19931 | * value |
Marko Mikulicic |
0:c0ecb8bf28eb | 19932 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19933 | V7_TRY(v7_get_throwing(v7, v, "toString", 8, &to_string_func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19934 | if (v7_is_callable(v7, to_string_func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19935 | V7_TRY(b_apply(v7, to_string_func, v, V7_UNDEFINED, 0, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19936 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19937 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19938 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19940 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19941 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19942 | v7_disown(v7, &to_string_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19944 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19945 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19946 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19947 | static const char *hex_digits = "0123456789abcdef"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19948 | static char *append_hex(char *buf, char *limit, uint8_t c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19949 | if (buf < limit) *buf++ = 'u'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19950 | if (buf < limit) *buf++ = '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19951 | if (buf < limit) *buf++ = '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19952 | if (buf < limit) *buf++ = hex_digits[(int) ((c >> 4) % 0xf)]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19953 | if (buf < limit) *buf++ = hex_digits[(int) (c & 0xf)]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19954 | return buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19955 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19956 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19957 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19958 | * Appends quoted s to buf. Any double quote contained in s will be escaped. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19959 | * Returns the number of characters that would have been added, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19960 | * like snprintf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19961 | * If size is zero it doesn't output anything but keeps counting. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19962 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19963 | static int snquote(char *buf, size_t size, const char *s, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19964 | char *limit = buf + size - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19965 | const char *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19966 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19967 | * String single character escape sequence: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19968 | * http://www.ecma-international.org/ecma-262/6.0/index.html#table-34 |
Marko Mikulicic |
0:c0ecb8bf28eb | 19969 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 19970 | * 0x8 -> \b |
Marko Mikulicic |
0:c0ecb8bf28eb | 19971 | * 0x9 -> \t |
Marko Mikulicic |
0:c0ecb8bf28eb | 19972 | * 0xa -> \n |
Marko Mikulicic |
0:c0ecb8bf28eb | 19973 | * 0xb -> \v |
Marko Mikulicic |
0:c0ecb8bf28eb | 19974 | * 0xc -> \f |
Marko Mikulicic |
0:c0ecb8bf28eb | 19975 | * 0xd -> \r |
Marko Mikulicic |
0:c0ecb8bf28eb | 19976 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19977 | const char *specials = "btnvfr"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19978 | size_t i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19980 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19981 | if (buf < limit) *buf++ = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19983 | for (end = s + len; s < end; s++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19984 | if (*s == '"' || *s == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19985 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19986 | if (buf < limit) *buf++ = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19987 | } else if (*s >= '\b' && *s <= '\r') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19988 | i += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19989 | if (buf < limit) *buf++ = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19990 | if (buf < limit) *buf++ = specials[*s - '\b']; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19991 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19992 | } else if ((unsigned char) *s < '\b' || (*s > '\r' && *s < ' ')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19993 | i += 6 /* \uXXXX */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19994 | if (buf < limit) *buf++ = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19995 | buf = append_hex(buf, limit, (uint8_t) *s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19996 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19997 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19998 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19999 | if (buf < limit) *buf++ = *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20002 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20003 | if (buf < limit) *buf++ = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20005 | if (size != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20006 | *buf = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20008 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20009 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20010 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20011 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20012 | * Returns whether the value of given type should be skipped when generating |
Marko Mikulicic |
0:c0ecb8bf28eb | 20013 | * JSON output |
Marko Mikulicic |
0:c0ecb8bf28eb | 20014 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20015 | static int should_skip_for_json(enum v7_type type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20016 | int ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20017 | switch (type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20018 | /* All permitted values */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20019 | case V7_TYPE_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20020 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20021 | case V7_TYPE_BOOLEAN_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20022 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20023 | case V7_TYPE_NUMBER_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20024 | case V7_TYPE_STRING: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20025 | case V7_TYPE_STRING_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20026 | case V7_TYPE_GENERIC_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20027 | case V7_TYPE_ARRAY_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20028 | case V7_TYPE_DATE_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20029 | case V7_TYPE_REGEXP_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20030 | case V7_TYPE_ERROR_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20031 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20032 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20033 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20034 | ret = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20035 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20036 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20037 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20038 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20040 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 20041 | V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20042 | size_t size, size_t *res_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20043 | uint8_t is_debug) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20044 | val_t el; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20045 | char *vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20046 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20047 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20048 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20050 | tmp_stack_push(&tf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20051 | tmp_stack_push(&tf, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20052 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20053 | * TODO(dfrank) : also push all `v7_val_t`s that are declared below |
Marko Mikulicic |
0:c0ecb8bf28eb | 20054 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20056 | if (size > 0) *buf = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20058 | if (!is_debug && should_skip_for_json(val_type(v7, v))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20059 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20061 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20062 | for (vp = v7->json_visited_stack.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20063 | vp < v7->json_visited_stack.buf + v7->json_visited_stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20064 | vp += sizeof(val_t)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20065 | if (*(val_t *) vp == v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20066 | strncpy(buf, "[Circular]", size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20067 | len = 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20068 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20069 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20070 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20072 | switch (val_type(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20073 | case V7_TYPE_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20074 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20075 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20076 | case V7_TYPE_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20077 | case V7_TYPE_CFUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20078 | case V7_TYPE_FOREIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20079 | /* For those types, regular `primitive_to_str()` works */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20080 | V7_TRY(primitive_to_str(v7, v, NULL, buf, size, &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20081 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20083 | case V7_TYPE_STRING: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20084 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20085 | * For strings we can't just use `primitive_to_str()`, because we need |
Marko Mikulicic |
0:c0ecb8bf28eb | 20086 | * quoted value |
Marko Mikulicic |
0:c0ecb8bf28eb | 20087 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20088 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20089 | const char *str = v7_get_string(v7, &v, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20090 | len = snquote(buf, size, str, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20091 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20094 | case V7_TYPE_DATE_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20095 | v7_val_t func = V7_UNDEFINED, val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20096 | V7_TRY(v7_get_throwing(v7, v, "toString", 8, &func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20097 | #if V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 20098 | if (!is_debug) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20099 | V7_TRY(v7_get_throwing(v7, v, "toJSON", 6, &func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20101 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20102 | V7_TRY(b_apply(v7, func, v, V7_UNDEFINED, 0, &val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20103 | V7_TRY(to_json_or_debug(v7, val, buf, size, &len, is_debug)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20104 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20105 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20106 | case V7_TYPE_GENERIC_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20107 | case V7_TYPE_BOOLEAN_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20108 | case V7_TYPE_STRING_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20109 | case V7_TYPE_NUMBER_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20110 | case V7_TYPE_REGEXP_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20111 | case V7_TYPE_ERROR_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20112 | /* TODO(imax): make it return the desired size of the buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20113 | char *b = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20114 | v7_val_t name = V7_UNDEFINED, val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20115 | v7_prop_attr_t attrs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20116 | const char *pname; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20117 | size_t nlen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20118 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20119 | struct prop_iter_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20120 | memset(&ctx, 0, sizeof(ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20121 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20122 | mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20123 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "{"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20124 | V7_TRY2(init_prop_iter_ctx(v7, v, 1 /*proxy-transparent*/, &ctx), |
Marko Mikulicic |
0:c0ecb8bf28eb | 20125 | clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20126 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20127 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20128 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20129 | V7_TRY2(next_prop(v7, &ctx, &name, &val, &attrs, &ok), clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20130 | if (!ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20131 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20132 | } else if (attrs & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20133 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20134 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20135 | pname = v7_get_string(v7, &name, &nlen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20136 | V7_TRY(v7_get_throwing(v7, v, pname, nlen, &val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20137 | if (!is_debug && should_skip_for_json(val_type(v7, val))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20138 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20139 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20140 | if (b - buf != 1) { /* Not the first property to be printed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20141 | b += c_snprintf(b, BUF_LEFT(size, b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20142 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20143 | s = v7_get_string(v7, &name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20144 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "\"%.*s\":", (int) n, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20145 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20146 | size_t tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20147 | V7_TRY2(to_json_or_debug(v7, val, b, BUF_LEFT(size, b - buf), &tmp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20148 | is_debug), |
Marko Mikulicic |
0:c0ecb8bf28eb | 20149 | clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20150 | b += tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20151 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20152 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20153 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20154 | v7->json_visited_stack.len -= sizeof(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20156 | clean_iter: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20157 | v7_destruct_prop_iter_ctx(v7, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20159 | len = b - buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20160 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20161 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20162 | case V7_TYPE_ARRAY_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20163 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20164 | char *b = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20165 | size_t i, alen = v7_array_length(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20166 | mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20167 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "["); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20168 | for (i = 0; i < alen; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20169 | el = v7_array_get2(v7, v, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20170 | if (has) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20171 | size_t tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20172 | if (!is_debug && should_skip_for_json(val_type(v7, el))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20173 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "null"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20174 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20175 | V7_TRY(to_json_or_debug(v7, el, b, BUF_LEFT(size, b - buf), &tmp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20176 | is_debug)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20177 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20178 | b += tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20179 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20180 | if (i != alen - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20181 | b += c_snprintf(b, BUF_LEFT(size, b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20182 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20183 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20184 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "]"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20185 | v7->json_visited_stack.len -= sizeof(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20186 | len = b - buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20187 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20188 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20189 | case V7_TYPE_CFUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20190 | V7_TRY(obj_value_of(v7, v, &v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20191 | len = c_snprintf(buf, size, "Function cfunc_%p", get_ptr(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20192 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20193 | case V7_TYPE_FUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20194 | V7_TRY(to_string(v7, v, NULL, buf, size, &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20195 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20197 | case V7_TYPE_MAX_OBJECT_TYPE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20198 | case V7_NUM_TYPES: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20199 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20201 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20202 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20204 | len = 0; /* for compilers that don't know about abort() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20205 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20207 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20208 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20209 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20210 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20211 | if (res_len != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20212 | *res_len = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20213 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20214 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20215 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20216 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20218 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 20219 | V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20220 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20221 | int is_truthy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20223 | is_truthy = ((v7_is_boolean(v) && v7_get_bool(v7, v)) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20224 | (v7_is_number(v) && v7_get_double(v7, v) != 0.0) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20225 | (v7_is_string(v) && v7_get_string(v7, &v, &len) && len > 0) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20226 | (v7_is_object(v))) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 20227 | v != V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20229 | return v7_mk_boolean(v7, is_truthy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20230 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20232 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20233 | * v7_stringify allocates a new buffer if value representation doesn't fit into |
Marko Mikulicic |
0:c0ecb8bf28eb | 20234 | * buf. Caller is responsible for freeing that buffer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20235 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20236 | char *v7_stringify(struct v7 *v7, val_t v, char *buf, size_t size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20237 | enum v7_stringify_mode mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20238 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20239 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20240 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20241 | char *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20243 | rcode = v7_stringify_throwing(v7, v, buf, size, mode, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20244 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20245 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20246 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20247 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20248 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20249 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20252 | buf[0] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20253 | ret = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20254 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20256 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20257 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20258 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20259 | enum v7_err v7_stringify_throwing(struct v7 *v7, val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20260 | size_t size, enum v7_stringify_mode mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20261 | char **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20262 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20263 | char *p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20264 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20265 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20266 | switch (mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20267 | case V7_STRINGIFY_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20268 | V7_TRY(to_string(v7, v, NULL, buf, size, &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20269 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20271 | case V7_STRINGIFY_JSON: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20272 | V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20273 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20275 | case V7_STRINGIFY_DEBUG: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20276 | V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20277 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20278 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20280 | /* fit null terminating byte */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20281 | if (len >= size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20282 | /* Buffer is not large enough. Allocate a bigger one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20283 | p = (char *) malloc(len + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20284 | V7_TRY(v7_stringify_throwing(v7, v, p, len + 1, mode, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20285 | assert(*res == p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20286 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20287 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20288 | *res = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20289 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20290 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20292 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20293 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20294 | * If we're going to throw, and we allocated a buffer, then free it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20295 | * But if we don't throw, then the caller will free it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20296 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20297 | if (rcode != V7_OK && p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20298 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20299 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20300 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20303 | int v7_is_truthy(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20304 | return v7_get_bool(v7, to_boolean_v(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20305 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20306 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 20307 | #line 1 "v7/src/shdata.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 20308 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20309 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20310 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 20311 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 20312 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20314 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20315 | /* Amalgamated: #include "v7/src/shdata.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20317 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 20318 | V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20319 | struct shdata *ret = |
Marko Mikulicic |
0:c0ecb8bf28eb | 20320 | (struct shdata *) calloc(1, sizeof(struct shdata) + size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20321 | shdata_retain(ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20322 | if (payload != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20323 | memcpy((char *) shdata_get_payload(ret), (char *) payload, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20324 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20325 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20326 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20328 | V7_PRIVATE struct shdata *shdata_create_from_string(const char *src) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20329 | return shdata_create(src, strlen(src) + 1 /*null-term*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20330 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20332 | V7_PRIVATE void shdata_retain(struct shdata *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20333 | p->refcnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20334 | assert(p->refcnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20335 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20337 | V7_PRIVATE void shdata_release(struct shdata *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20338 | assert(p->refcnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20339 | p->refcnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20340 | if (p->refcnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20341 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20343 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20345 | V7_PRIVATE void *shdata_get_payload(struct shdata *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20346 | return (char *) p + sizeof(*p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20347 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20348 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20349 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 20350 | #line 1 "v7/src/gc.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 20351 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20352 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20353 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 20354 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 20355 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20357 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20358 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20359 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20360 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20361 | /* Amalgamated: #include "v7/src/freeze.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20362 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20363 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20364 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20365 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20366 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20367 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20368 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20369 | /* Amalgamated: #include "v7/src/heapusage.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20371 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 20372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20373 | #ifdef V7_STACK_GUARD_MIN_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20374 | void *v7_sp_limit = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20375 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20377 | void gc_mark_string(struct v7 *, val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20379 | static struct gc_block *gc_new_block(struct gc_arena *a, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20380 | static void gc_free_block(struct gc_block *b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20381 | static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20382 | static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20383 | static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20385 | V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20386 | return (struct v7_generic_object *) gc_alloc_cell(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20387 | &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20390 | V7_PRIVATE struct v7_property *new_property(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20391 | return (struct v7_property *) gc_alloc_cell(v7, &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20392 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20394 | V7_PRIVATE struct v7_js_function *new_function(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20395 | return (struct v7_js_function *) gc_alloc_cell(v7, &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20396 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20398 | V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20399 | struct gc_tmp_frame frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20400 | frame.v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20401 | frame.pos = v7->tmp_stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20402 | return frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20403 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20405 | V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *tf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20406 | tf->v7->tmp_stack.len = tf->pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20409 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20410 | * TODO(mkm): perhaps it's safer to keep val_t in the temporary |
Marko Mikulicic |
0:c0ecb8bf28eb | 20411 | * roots stack, instead of keeping val_t*, in order to be better |
Marko Mikulicic |
0:c0ecb8bf28eb | 20412 | * able to debug the relocating GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20413 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20414 | V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *tf, val_t *vp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20415 | mbuf_append(&tf->v7->tmp_stack, (char *) &vp, sizeof(val_t *)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20417 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20418 | /* Initializes a new arena. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20419 | V7_PRIVATE void gc_arena_init(struct gc_arena *a, size_t cell_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20420 | size_t initial_size, size_t size_increment, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20421 | const char *name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20422 | assert(cell_size >= sizeof(uintptr_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20424 | memset(a, 0, sizeof(*a)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20425 | a->cell_size = cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20426 | a->name = name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20427 | a->size_increment = size_increment; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20428 | a->blocks = gc_new_block(a, initial_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20429 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20431 | V7_PRIVATE void gc_arena_destroy(struct v7 *v7, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20432 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20434 | if (a->blocks != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20435 | gc_sweep(v7, a, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20436 | for (b = a->blocks; b != NULL;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20437 | struct gc_block *tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20438 | tmp = b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20439 | b = b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20440 | gc_free_block(tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20442 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20445 | static void gc_free_block(struct gc_block *b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20446 | free(b->base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20447 | free(b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20448 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20450 | static struct gc_block *gc_new_block(struct gc_arena *a, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20451 | struct gc_cell *cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20452 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20453 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20454 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20455 | b = (struct gc_block *) calloc(1, sizeof(*b)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20456 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20457 | if (b == NULL) abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20459 | b->size = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20460 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20461 | b->base = (struct gc_cell *) calloc(a->cell_size, b->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20462 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20463 | if (b->base == NULL) abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20465 | for (cur = GC_CELL_OP(a, b->base, +, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20466 | cur < GC_CELL_OP(a, b->base, +, b->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20467 | cur = GC_CELL_OP(a, cur, +, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20468 | cur->head.link = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20469 | a->free = cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20470 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20472 | return b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20473 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20475 | V7_PRIVATE void *gc_alloc_cell(struct v7 *v7, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20476 | #if V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 20477 | struct gc_cell *r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20478 | maybe_gc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20479 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20480 | r = (struct gc_cell *) calloc(1, a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20481 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20482 | mbuf_append(&v7->malloc_trace, &r, sizeof(r)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20483 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20484 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 20485 | struct gc_cell *r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20486 | if (a->free == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20487 | if (!maybe_gc(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20488 | /* GC is inhibited, so, schedule invocation for later */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20489 | v7->need_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20490 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20492 | if (a->free == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20493 | struct gc_block *b = gc_new_block(a, a->size_increment); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20494 | b->next = a->blocks; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20495 | a->blocks = b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20498 | r = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20499 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20500 | UNMARK(r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20502 | a->free = r->head.link; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20503 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20504 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20505 | a->allocations++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20506 | a->alive++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20507 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20509 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20510 | * TODO(mkm): minor opt possible since most of the fields |
Marko Mikulicic |
0:c0ecb8bf28eb | 20511 | * are overwritten downstream, but not worth the yak shave time |
Marko Mikulicic |
0:c0ecb8bf28eb | 20512 | * when fields are added to GC-able structures */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20513 | memset(r, 0, a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20514 | return (void *) r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20515 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20516 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20518 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 20519 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20520 | * Scans trough the memory blocks registered in the malloc trace. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20521 | * Free the unmarked ones and reset the mark on the rest. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20522 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20523 | void gc_sweep_malloc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20524 | struct gc_cell **cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20525 | for (cur = (struct gc_cell **) v7->malloc_trace.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20526 | cur < (struct gc_cell **) (v7->malloc_trace.buf + v7->malloc_trace.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20527 | cur++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20528 | if (*cur == NULL) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20529 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20530 | if (MARKED(*cur)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20531 | UNMARK(*cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20532 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20533 | free(*cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20534 | /* TODO(mkm): compact malloc trace buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20535 | *cur = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20536 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20537 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20538 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20539 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20540 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20541 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20542 | * Scans the arena and add all unmarked cells to the free list. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20543 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20544 | * Empty blocks get deallocated. The head of the free list will contais cells |
Marko Mikulicic |
0:c0ecb8bf28eb | 20545 | * from the last (oldest) block. Cells will thus be allocated in block order. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20546 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20547 | void gc_sweep(struct v7 *v7, struct gc_arena *a, size_t start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20548 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20549 | struct gc_cell *cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20550 | struct gc_block **prevp = &a->blocks; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20551 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20552 | a->alive = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20553 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20555 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20556 | * Before we sweep, we should mark all free cells in a way that is |
Marko Mikulicic |
0:c0ecb8bf28eb | 20557 | * distinguishable from marked used cells. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20558 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20559 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20560 | struct gc_cell *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20561 | for (cur = a->free; cur != NULL; cur = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20562 | next = cur->head.link; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20563 | MARK_FREE(cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20564 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20565 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20567 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20568 | * We'll rebuild the whole `free` list, so initially we just reset it |
Marko Mikulicic |
0:c0ecb8bf28eb | 20569 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20570 | a->free = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20572 | for (b = a->blocks; b != NULL;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20573 | size_t freed_in_block = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20574 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20575 | * if it turns out that this block is 100% garbage |
Marko Mikulicic |
0:c0ecb8bf28eb | 20576 | * we can release the whole block, but the addition |
Marko Mikulicic |
0:c0ecb8bf28eb | 20577 | * of it's cells to the free list has to be undone. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20578 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20579 | struct gc_cell *prev_free = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20581 | for (cur = GC_CELL_OP(a, b->base, +, start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20582 | cur < GC_CELL_OP(a, b->base, +, b->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20583 | cur = GC_CELL_OP(a, cur, +, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20584 | if (MARKED(cur)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20585 | /* The cell is used and marked */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20586 | UNMARK(cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20587 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20588 | a->alive++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20589 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20590 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20591 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20592 | * The cell is either: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20593 | * - free |
Marko Mikulicic |
0:c0ecb8bf28eb | 20594 | * - garbage that's about to be freed |
Marko Mikulicic |
0:c0ecb8bf28eb | 20595 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20597 | if (MARKED_FREE(cur)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20598 | /* The cell is free, so, just unmark it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20599 | UNMARK_FREE(cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20600 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20601 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20602 | * The cell is used and should be freed: call the destructor and |
Marko Mikulicic |
0:c0ecb8bf28eb | 20603 | * reset the memory |
Marko Mikulicic |
0:c0ecb8bf28eb | 20604 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20605 | if (a->destructor != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20606 | a->destructor(v7, cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20607 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20608 | memset(cur, 0, a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20609 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20611 | /* Add this cell to the `free` list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20612 | cur->head.link = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20613 | a->free = cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20614 | freed_in_block++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20615 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20616 | a->garbage++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20617 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20618 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20619 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20621 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20622 | * don't free the initial block, which is at the tail |
Marko Mikulicic |
0:c0ecb8bf28eb | 20623 | * because it has a special size aimed at reducing waste |
Marko Mikulicic |
0:c0ecb8bf28eb | 20624 | * and simplifying initial startup. TODO(mkm): improve |
Marko Mikulicic |
0:c0ecb8bf28eb | 20625 | * */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20626 | if (b->next != NULL && freed_in_block == b->size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20627 | *prevp = b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20628 | gc_free_block(b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20629 | b = *prevp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20630 | a->free = prev_free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20631 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20632 | prevp = &b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20633 | b = b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20634 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20636 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20638 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20639 | * dense arrays contain only one property pointing to an mbuf with array values. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20640 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20641 | V7_PRIVATE void gc_mark_dense_array(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20642 | struct v7_generic_object *obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20643 | val_t v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20644 | struct mbuf *mbuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20645 | val_t *vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20646 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20647 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 20648 | /* TODO(mkm): use this when dense array promotion is implemented */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20649 | v = obj->properties->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20650 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 20651 | v = v7_get(v7, v7_object_to_value(&obj->base), "", 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20652 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20654 | mbuf = (struct mbuf *) v7_get_ptr(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20656 | /* function scope pointer is aliased to the object's prototype pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20657 | gc_mark(v7, v7_object_to_value(obj_prototype(v7, &obj->base))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20658 | MARK(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20659 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20660 | if (mbuf == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20661 | for (vp = (val_t *) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20662 | gc_mark(v7, *vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20663 | gc_mark_string(v7, vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20664 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20665 | UNMARK(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20666 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20668 | V7_PRIVATE void gc_mark(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20669 | struct v7_object *obj_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20670 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20671 | struct v7_property *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20673 | if (!v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20674 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20675 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20676 | obj_base = get_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20678 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20679 | * we ignore objects that are not managed by V7 heap, such as frozen |
Marko Mikulicic |
0:c0ecb8bf28eb | 20680 | * objects, especially when on flash. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20681 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20682 | if (obj_base->attributes & V7_OBJ_OFF_HEAP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20683 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20686 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20687 | * we treat all object like things like objects but they might be functions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20688 | * gc_gheck_val checks the appropriate arena per actual value type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20689 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20690 | if (!gc_check_val(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20691 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20692 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20694 | if (MARKED(obj_base)) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20696 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20697 | if (v7->freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20698 | freeze_obj(v7, v7->freeze_file, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20700 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20702 | if (obj_base->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20703 | struct v7_generic_object *obj = get_generic_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20704 | gc_mark_dense_array(v7, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20705 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20707 | /* mark object itself, and its properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20708 | for ((prop = obj_base->properties), MARK(obj_base); prop != NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20709 | prop = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20710 | if (prop->attributes & _V7_PROPERTY_OFF_HEAP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20711 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20712 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20713 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20714 | if (!gc_check_ptr(&v7->property_arena, prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20715 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20716 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20717 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20718 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20719 | if (v7->freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20720 | freeze_prop(v7, v7->freeze_file, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20721 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20722 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20723 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20724 | gc_mark_string(v7, &prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20725 | gc_mark_string(v7, &prop->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20726 | gc_mark(v7, prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20727 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20728 | next = prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20729 | MARK(prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20732 | /* mark object's prototype */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20733 | gc_mark(v7, v7_get_proto(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20735 | if (is_js_function(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20736 | struct v7_js_function *func = get_js_function_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20737 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20738 | /* mark function's scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20739 | gc_mark(v7, v7_object_to_value(&func->scope->base)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20741 | if (func->bcode != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20742 | gc_mark_vec_val(v7, &func->bcode->lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20743 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20744 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20745 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20746 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20747 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20749 | V7_PRIVATE size_t gc_arena_size(struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20750 | size_t size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20751 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20752 | for (b = a->blocks; b != NULL; b = b->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20753 | size += b->size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20754 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20755 | return size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20756 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20758 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20759 | * TODO(dfrank): move to core |
Marko Mikulicic |
0:c0ecb8bf28eb | 20760 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20761 | int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20762 | switch (what) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20763 | case V7_HEAP_STAT_HEAP_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20764 | return gc_arena_size(&v7->generic_object_arena) * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20765 | v7->generic_object_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20766 | gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20767 | gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20768 | case V7_HEAP_STAT_HEAP_USED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20769 | return v7->generic_object_arena.alive * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20770 | v7->generic_object_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20771 | v7->function_arena.alive * v7->function_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20772 | v7->property_arena.alive * v7->property_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20773 | case V7_HEAP_STAT_STRING_HEAP_RESERVED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20774 | return v7->owned_strings.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20775 | case V7_HEAP_STAT_STRING_HEAP_USED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20776 | return v7->owned_strings.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20777 | case V7_HEAP_STAT_OBJ_HEAP_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20778 | return gc_arena_size(&v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20779 | case V7_HEAP_STAT_OBJ_HEAP_FREE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20780 | return gc_arena_size(&v7->generic_object_arena) - |
Marko Mikulicic |
0:c0ecb8bf28eb | 20781 | v7->generic_object_arena.alive; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20782 | case V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20783 | return v7->generic_object_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20784 | case V7_HEAP_STAT_FUNC_HEAP_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20785 | return gc_arena_size(&v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20786 | case V7_HEAP_STAT_FUNC_HEAP_FREE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20787 | return gc_arena_size(&v7->function_arena) - v7->function_arena.alive; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20788 | case V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20789 | return v7->function_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20790 | case V7_HEAP_STAT_PROP_HEAP_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20791 | return gc_arena_size(&v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20792 | case V7_HEAP_STAT_PROP_HEAP_FREE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20793 | return gc_arena_size(&v7->property_arena) - v7->property_arena.alive; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20794 | case V7_HEAP_STAT_PROP_HEAP_CELL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20795 | return v7->property_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20796 | case V7_HEAP_STAT_FUNC_AST_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20797 | return v7->function_arena_ast_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20798 | case V7_HEAP_STAT_BCODE_OPS_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20799 | return v7->bcode_ops_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20800 | case V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20801 | return v7->bcode_lit_total_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20802 | case V7_HEAP_STAT_BCODE_LIT_DESER_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20803 | return v7->bcode_lit_deser_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20804 | case V7_HEAP_STAT_FUNC_OWNED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20805 | return v7->owned_values.len / sizeof(val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20806 | case V7_HEAP_STAT_FUNC_OWNED_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20807 | return v7->owned_values.size / sizeof(val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20808 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20810 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20811 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20812 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20813 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20814 | V7_PRIVATE void gc_dump_arena_stats(const char *msg, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20815 | (void) msg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20816 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20817 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 20818 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20819 | if (a->verbose) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20820 | fprintf(stderr, "%s: total allocations %lu, max %lu, alive %lu\n", msg, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20821 | (long unsigned int) a->allocations, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20822 | (long unsigned int) gc_arena_size(a), (long unsigned int) a->alive); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20823 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20824 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20825 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20826 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20828 | V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20829 | return (((uint64_t)(uintptr_t) get_ptr(v)) & ~V7_TAG_MASK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 20830 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20831 | & 0xFFFFFFFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 20832 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20833 | ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20834 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20836 | V7_PRIVATE val_t gc_string_val_from_offset(uint64_t s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20837 | return s | V7_TAG_STRING_O; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20838 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20840 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20842 | static uint16_t next_asn(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20843 | if (v7->gc_next_asn == 0xFFFF) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20844 | /* Wrap around explicitly. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20845 | v7->gc_next_asn = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20846 | return 0xFFFF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20848 | return v7->gc_next_asn++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20849 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20850 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20851 | uint16_t gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20852 | uint16_t asn = next_asn(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20853 | (void) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20854 | (void) len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20855 | #ifdef V7_GC_VERBOSE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20856 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20857 | * ESP SDK printf cannot cope with null strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 20858 | * as created by s_concat. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20859 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20860 | if (str == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20861 | fprintf(stderr, "GC ASN %d: <nil>\n", asn); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20862 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20863 | fprintf(stderr, "GC ASN %d: \"%.*s\"\n", asn, (int) len, str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20864 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20865 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20866 | #ifdef V7_GC_PANIC_ON_ASN |
Marko Mikulicic |
0:c0ecb8bf28eb | 20867 | if (asn == (V7_GC_PANIC_ON_ASN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20868 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20869 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20870 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20871 | return asn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20872 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20874 | int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20875 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20876 | * This functions attempts to handle integer wraparound in a naive way and |
Marko Mikulicic |
0:c0ecb8bf28eb | 20877 | * will give false positives when more than 65536 strings are allocated |
Marko Mikulicic |
0:c0ecb8bf28eb | 20878 | * between GC runs. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20879 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20880 | int r = (n >= v7->gc_min_asn && n < v7->gc_next_asn) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20881 | (v7->gc_min_asn > v7->gc_next_asn && |
Marko Mikulicic |
0:c0ecb8bf28eb | 20882 | (n >= v7->gc_min_asn || n < v7->gc_next_asn)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20883 | if (!r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20884 | fprintf(stderr, "GC ASN %d is not in [%d,%d)\n", n, v7->gc_min_asn, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20885 | v7->gc_next_asn); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20887 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20890 | void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20891 | if (!gc_is_valid_allocation_seqn(v7, n)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20892 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20893 | * TODO(dfrank) throw exception if V7_GC_ASN_PANIC is not defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20894 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20895 | #if 0 && !defined(V7_GC_ASN_PANIC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 20896 | throw_exception(v7, INTERNAL_ERROR, "Invalid ASN: %d", (int) n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20897 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 20898 | fprintf(stderr, "Invalid ASN: %d\n", (int) n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20899 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20900 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20901 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20902 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20904 | #endif /* V7_DISABLE_STR_ALLOC_SEQ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20906 | /* Mark a string value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20907 | void gc_mark_string(struct v7 *v7, val_t *v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20908 | val_t h, tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20909 | char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20911 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20913 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20914 | * If a value points to an unmarked string we shall: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20915 | * 1. save the first 6 bytes of the string |
Marko Mikulicic |
0:c0ecb8bf28eb | 20916 | * since we need to be able to distinguish real values from |
Marko Mikulicic |
0:c0ecb8bf28eb | 20917 | * the saved first 6 bytes of the string, we need to tag the chunk |
Marko Mikulicic |
0:c0ecb8bf28eb | 20918 | * as V7_TAG_STRING_C |
Marko Mikulicic |
0:c0ecb8bf28eb | 20919 | * 2. encode value's address (v) into the first 6 bytes of the string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20920 | * 3. put the saved 8 bytes (tag + chunk) back into the value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20921 | * 4. mark the string by putting '\1' in the NUL terminator of the previous |
Marko Mikulicic |
0:c0ecb8bf28eb | 20922 | * string chunk. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20923 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20924 | * If a value points to an already marked string we shall: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20925 | * (0, <6 bytes of a pointer to a val_t>), hence we have to skip |
Marko Mikulicic |
0:c0ecb8bf28eb | 20926 | * the first byte. We tag the value pointer as a V7_TAG_FOREIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 20927 | * so that it won't be followed during recursive mark. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20928 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20929 | * ... the rest is the same |
Marko Mikulicic |
0:c0ecb8bf28eb | 20930 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20931 | * Note: 64-bit pointers can be represented with 48-bits |
Marko Mikulicic |
0:c0ecb8bf28eb | 20932 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20934 | /* clang-format on */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20936 | if ((*v & V7_TAG_MASK) != V7_TAG_STRING_O) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20937 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20938 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20940 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20941 | if (v7->freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20942 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20943 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20944 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20946 | #ifdef V7_GC_VERBOSE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20947 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20948 | uint16_t asn = (*v >> 32) & 0xFFFF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20949 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20950 | fprintf(stderr, "GC marking ASN %d: '%s'\n", asn, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20951 | v7_get_string(v7, v, &size)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20952 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20953 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20955 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20956 | gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20957 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20959 | s = v7->owned_strings.buf + gc_string_val_to_offset(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20960 | assert(s < v7->owned_strings.buf + v7->owned_strings.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20961 | if (s[-1] == '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20962 | memcpy(&tmp, s, sizeof(tmp) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20963 | tmp |= V7_TAG_STRING_C; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20964 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20965 | memcpy(&tmp, s, sizeof(tmp) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20966 | tmp |= V7_TAG_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20967 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20969 | h = (val_t)(uintptr_t) v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20970 | s[-1] = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20971 | memcpy(s, &h, sizeof(h) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20972 | memcpy(v, &tmp, sizeof(tmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20973 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20975 | void gc_compact_strings(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20976 | char *p = v7->owned_strings.buf + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20977 | uint64_t h, next, head = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20978 | int len, llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20980 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20981 | v7->gc_min_asn = v7->gc_next_asn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20982 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20983 | while (p < v7->owned_strings.buf + v7->owned_strings.len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20984 | if (p[-1] == '\1') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20985 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20986 | /* Not using gc_next_allocation_seqn() as we don't have full string. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20987 | uint16_t asn = next_asn(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20988 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20989 | /* relocate and update ptrs */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20990 | h = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20991 | memcpy(&h, p, sizeof(h) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20993 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20994 | * relocate pointers until we find the tail. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20995 | * The tail is marked with V7_TAG_STRING_C, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20996 | * while val_t link pointers are tagged with V7_TAG_FOREIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 20997 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20998 | for (; (h & V7_TAG_MASK) != V7_TAG_STRING_C; h = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20999 | h &= ~V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21000 | memcpy(&next, (char *) (uintptr_t) h, sizeof(h)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21002 | *(val_t *) (uintptr_t) h = gc_string_val_from_offset(head) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21003 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21004 | | ((val_t) asn << 32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21005 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21006 | ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21008 | h &= ~V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21010 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21011 | * the tail contains the first 6 bytes we stole from |
Marko Mikulicic |
0:c0ecb8bf28eb | 21012 | * the actual string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21013 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21014 | len = decode_varint((unsigned char *) &h, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21015 | len += llen + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21017 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21018 | * restore the saved 6 bytes |
Marko Mikulicic |
0:c0ecb8bf28eb | 21019 | * TODO(mkm): think about endianness |
Marko Mikulicic |
0:c0ecb8bf28eb | 21020 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21021 | memcpy(p, &h, sizeof(h) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21022 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21023 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21024 | * and relocate the string data by packing it to the left. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21025 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21026 | memmove(v7->owned_strings.buf + head, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21027 | v7->owned_strings.buf[head - 1] = 0x0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21028 | #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21029 | fprintf(stderr, "GC updated ASN %d: \"%.*s\"\n", asn, len - llen - 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21030 | v7->owned_strings.buf + head + llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21031 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21032 | p += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21033 | head += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21034 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21035 | len = decode_varint((unsigned char *) p, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21036 | len += llen + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21038 | p += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21040 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21042 | #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21043 | fprintf(stderr, "GC valid ASN range: [%d,%d)\n", v7->gc_min_asn, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21044 | v7->gc_next_asn); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21045 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21046 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21047 | v7->owned_strings.len = head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21050 | void gc_dump_owned_strings(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21051 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21052 | for (i = 0; i < v7->owned_strings.len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21053 | if (isprint((unsigned char) v7->owned_strings.buf[i])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21054 | fputc(v7->owned_strings.buf[i], stderr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21055 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21056 | fputc('.', stderr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21057 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21059 | fputc('\n', stderr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21061 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21062 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21063 | * builting on gcc, tried out by redefining it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21064 | * Using null pointer as base can trigger undefined behavior, hence |
Marko Mikulicic |
0:c0ecb8bf28eb | 21065 | * a portable workaround that involves a valid yet dummy pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21066 | * It's meant to be used as a contant expression. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21067 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21068 | #ifndef offsetof |
Marko Mikulicic |
0:c0ecb8bf28eb | 21069 | #define offsetof(st, m) (((ptrdiff_t)(&((st *) 32)->m)) - 32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21070 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21072 | V7_PRIVATE void compute_need_gc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21073 | struct mbuf *m = &v7->owned_strings; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21074 | if ((double) m->len / (double) m->size > 0.9) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21075 | v7->need_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21076 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21077 | /* TODO(mkm): check free heap */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21078 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21079 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21080 | V7_PRIVATE int maybe_gc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21081 | if (!v7->inhibit_gc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21082 | v7_gc(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21083 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21084 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21085 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21086 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21087 | #if defined(V7_GC_VERBOSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21088 | static int gc_pass = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21089 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21091 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21092 | * mark an array of `val_t` values (*not pointers* to them) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21093 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21094 | static void gc_mark_val_array(struct v7 *v7, val_t *vals, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21095 | val_t *vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21096 | for (vp = vals; vp < vals + len; vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21097 | gc_mark(v7, *vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21098 | gc_mark_string(v7, vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21099 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21102 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21103 | * mark an mbuf containing *pointers* to `val_t` values |
Marko Mikulicic |
0:c0ecb8bf28eb | 21104 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21105 | static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21106 | val_t **vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21107 | for (vp = (val_t **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21108 | gc_mark(v7, **vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21109 | gc_mark_string(v7, *vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21110 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21113 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21114 | * mark an mbuf containing `val_t` values (*not pointers* to them) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21115 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21116 | static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21117 | gc_mark_val_array(v7, (val_t *) mbuf->buf, mbuf->len / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21118 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21119 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21120 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21121 | * mark a vector containing `val_t` values (*not pointers* to them) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21122 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21123 | static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21124 | gc_mark_val_array(v7, (val_t *) vec->p, vec->len / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21125 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21126 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21127 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21128 | * mark an mbuf containing foreign pointers to `struct bcode` |
Marko Mikulicic |
0:c0ecb8bf28eb | 21129 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21130 | static void gc_mark_mbuf_bcode_pt(struct v7 *v7, const struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21131 | struct bcode **vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21132 | for (vp = (struct bcode **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21133 | vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21134 | gc_mark_vec_val(v7, &(*vp)->lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21135 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21136 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21138 | static void gc_mark_call_stack_private( |
Marko Mikulicic |
0:c0ecb8bf28eb | 21139 | struct v7 *v7, struct v7_call_frame_private *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21140 | gc_mark_val_array(v7, (val_t *) &call_stack->vals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21141 | sizeof(call_stack->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21142 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21144 | static void gc_mark_call_stack_cfunc(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21145 | struct v7_call_frame_cfunc *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21146 | gc_mark_val_array(v7, (val_t *) &call_stack->vals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21147 | sizeof(call_stack->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21148 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21150 | static void gc_mark_call_stack_bcode(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21151 | struct v7_call_frame_bcode *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21152 | gc_mark_val_array(v7, (val_t *) &call_stack->vals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21153 | sizeof(call_stack->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21156 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21157 | * mark `struct v7_call_frame` and all its back-linked frames |
Marko Mikulicic |
0:c0ecb8bf28eb | 21158 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21159 | static void gc_mark_call_stack(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21160 | struct v7_call_frame_base *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21161 | while (call_stack != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21162 | if (call_stack->type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21163 | gc_mark_call_stack_bcode(v7, (struct v7_call_frame_bcode *) call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21164 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21166 | if (call_stack->type_mask & V7_CALL_FRAME_MASK_PRIVATE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21167 | gc_mark_call_stack_private(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21168 | (struct v7_call_frame_private *) call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21169 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21170 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21171 | if (call_stack->type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21172 | gc_mark_call_stack_cfunc(v7, (struct v7_call_frame_cfunc *) call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21175 | call_stack = call_stack->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21176 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21177 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21178 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21179 | /* Perform garbage collection */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21180 | void v7_gc(struct v7 *v7, int full) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21181 | #ifdef V7_DISABLE_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 21182 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21183 | (void) full; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21184 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21185 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21187 | #if defined(V7_GC_VERBOSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21188 | fprintf(stderr, "V7 GC pass %d\n", ++gc_pass); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21189 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21191 | gc_dump_arena_stats("Before GC objects", &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21192 | gc_dump_arena_stats("Before GC functions", &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21193 | gc_dump_arena_stats("Before GC properties", &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21195 | gc_mark_call_stack(v7, v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21197 | gc_mark_val_array(v7, (val_t *) &v7->vals, sizeof(v7->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21198 | /* mark all items on bcode stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21199 | gc_mark_mbuf_val(v7, &v7->stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21201 | /* mark literals and names of all the active bcodes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21202 | gc_mark_mbuf_bcode_pt(v7, &v7->act_bcodes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21204 | gc_mark_mbuf_pt(v7, &v7->tmp_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21205 | gc_mark_mbuf_pt(v7, &v7->owned_values); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21207 | gc_compact_strings(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21209 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 21210 | gc_sweep_malloc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21211 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21212 | gc_sweep(v7, &v7->generic_object_arena, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21213 | gc_sweep(v7, &v7->function_arena, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21214 | gc_sweep(v7, &v7->property_arena, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21215 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21216 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21217 | gc_dump_arena_stats("After GC objects", &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21218 | gc_dump_arena_stats("After GC functions", &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21219 | gc_dump_arena_stats("After GC properties", &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21220 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21221 | if (full) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21222 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21223 | * In case of full GC, we also resize strings buffer, but we still leave |
Marko Mikulicic |
0:c0ecb8bf28eb | 21224 | * some extra space (at most, `_V7_STRING_BUF_RESERVE`) in order to avoid |
Marko Mikulicic |
0:c0ecb8bf28eb | 21225 | * frequent reallocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 21226 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21227 | size_t trimmed_size = v7->owned_strings.len + _V7_STRING_BUF_RESERVE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21228 | if (trimmed_size < v7->owned_strings.size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21229 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21230 | mbuf_resize(&v7->owned_strings, trimmed_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21231 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21232 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21233 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21234 | #endif /* V7_DISABLE_GC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21235 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21237 | V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21238 | if (is_js_function(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21239 | return gc_check_ptr(&v7->function_arena, get_js_function_struct(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21240 | } else if (v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21241 | return gc_check_ptr(&v7->generic_object_arena, get_object_struct(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21242 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21243 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21244 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21245 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21246 | V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21247 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 21248 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21249 | (void) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21250 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21251 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21252 | const struct gc_cell *p = (const struct gc_cell *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21253 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21254 | for (b = a->blocks; b != NULL; b = b->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21255 | if (p >= b->base && p < GC_CELL_OP(a, b->base, +, b->size)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21256 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21257 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21258 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21259 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21260 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21261 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21262 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 21263 | #line 1 "v7/src/freeze.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21264 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21265 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21266 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 21267 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 21268 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21270 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21271 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21272 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21273 | /* Amalgamated: #include "v7/src/freeze.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21274 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21275 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21276 | /* Amalgamated: #include "common/base64.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21277 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21278 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21279 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 21280 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21281 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 21282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21283 | V7_PRIVATE void freeze(struct v7 *v7, char *filename) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21284 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21286 | v7->freeze_file = fopen(filename, "w"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21287 | assert(v7->freeze_file != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21289 | #ifndef V7_FREEZE_NOT_READONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 21290 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21291 | * We have to remove `global` from the global object since |
Marko Mikulicic |
0:c0ecb8bf28eb | 21292 | * when thawing global will actually be a new mutable object |
Marko Mikulicic |
0:c0ecb8bf28eb | 21293 | * living on the heap. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21294 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21295 | v7_del(v7, v7->vals.global_object, "global", 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21296 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21298 | for (i = 0; i < sizeof(v7->vals) / sizeof(val_t); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21299 | val_t v = ((val_t *) &v7->vals)[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21300 | fprintf(v7->freeze_file, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21301 | "{\"type\":\"global\", \"idx\":%zu, \"value\":\"%p\"}\n", i, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21302 | (void *) (v7_is_object(v) ? get_object_struct(v) : 0x0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21303 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21305 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21306 | * since v7->freeze_file is not NULL this will cause freeze_obj and |
Marko Mikulicic |
0:c0ecb8bf28eb | 21307 | * freeze_prop to be called for each reachable object and property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21308 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21309 | v7_gc(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21310 | assert(v7->stack.len == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21312 | fclose(v7->freeze_file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21313 | v7->freeze_file = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21314 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21316 | static char *freeze_vec(struct v7_vec *vec) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21317 | char *res = (char *) malloc(512 + vec->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21318 | res[0] = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21319 | cs_base64_encode((const unsigned char *) vec->p, vec->len, &res[1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21320 | strcat(res, "\""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21321 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21324 | V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21325 | struct v7_object *obj_base = get_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21326 | unsigned int attrs = V7_OBJ_OFF_HEAP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21328 | #ifndef V7_FREEZE_NOT_READONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 21329 | attrs |= V7_OBJ_NOT_EXTENSIBLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21330 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21332 | if (is_js_function(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21333 | struct v7_js_function *func = get_js_function_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21334 | struct bcode *bcode = func->bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21335 | char *jops = freeze_vec(&bcode->ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21336 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21338 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21339 | "{\"type\":\"func\", \"addr\":\"%p\", \"props\":\"%p\", " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21340 | "\"attrs\":%d, \"scope\":\"%p\", \"bcode\":\"%p\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21341 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21342 | ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21343 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21344 | "}\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21345 | (void *) obj_base, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21346 | (void *) ((uintptr_t) obj_base->properties & ~0x1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 21347 | obj_base->attributes | attrs, (void *) func->scope, (void *) bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 21348 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21349 | , |
Marko Mikulicic |
0:c0ecb8bf28eb | 21350 | obj_base->entity_id_base, obj_base->entity_id_spec |
Marko Mikulicic |
0:c0ecb8bf28eb | 21351 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21352 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21353 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21354 | "{\"type\":\"bcode\", \"addr\":\"%p\", \"args_cnt\":%d, " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21355 | "\"names_cnt\":%d, " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21356 | "\"strict_mode\": %d, \"func_name_present\": %d, \"ops\":%s, " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21357 | "\"lit\": [", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21358 | (void *) bcode, bcode->args_cnt, bcode->names_cnt, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21359 | bcode->strict_mode, bcode->func_name_present, jops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21361 | for (i = 0; (size_t) i < bcode->lit.len / sizeof(val_t); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21362 | val_t v = ((val_t *) bcode->lit.p)[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21363 | const char *str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21365 | if (((v & V7_TAG_MASK) == V7_TAG_STRING_O || |
Marko Mikulicic |
0:c0ecb8bf28eb | 21366 | (v & V7_TAG_MASK) == V7_TAG_STRING_F) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 21367 | (str = v7_get_cstring(v7, &v)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21368 | fprintf(f, "{\"str\": \"%s\"}", str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21369 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21370 | fprintf(f, "{\"val\": \"0x%" INT64_X_FMT "\"}", v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21371 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21372 | if ((size_t) i != bcode->lit.len / sizeof(val_t) - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21373 | fprintf(f, ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21374 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21375 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21377 | fprintf(f, "]}\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21378 | free(jops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21379 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21380 | struct v7_generic_object *gob = get_generic_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21381 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21382 | "{\"type\":\"obj\", \"addr\":\"%p\", \"props\":\"%p\", " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21383 | "\"attrs\":%d, \"proto\":\"%p\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21384 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21385 | ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21386 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21387 | "}\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21388 | (void *) obj_base, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21389 | (void *) ((uintptr_t) obj_base->properties & ~0x1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 21390 | obj_base->attributes | attrs, (void *) gob->prototype |
Marko Mikulicic |
0:c0ecb8bf28eb | 21391 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21392 | , |
Marko Mikulicic |
0:c0ecb8bf28eb | 21393 | obj_base->entity_id_base, obj_base->entity_id_spec |
Marko Mikulicic |
0:c0ecb8bf28eb | 21394 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21395 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21396 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21397 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21398 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21399 | V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21400 | unsigned int attrs = _V7_PROPERTY_OFF_HEAP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21401 | #ifndef V7_FREEZE_NOT_READONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 21402 | attrs |= V7_PROPERTY_NON_WRITABLE | V7_PROPERTY_NON_CONFIGURABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21403 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21405 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21406 | "{\"type\":\"prop\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21407 | " \"addr\":\"%p\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21408 | " \"next\":\"%p\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21409 | " \"attrs\":%d," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21410 | " \"name\":\"0x%" INT64_X_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 21411 | "\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21412 | " \"value_type\":%d," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21413 | " \"value\":\"0x%" INT64_X_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 21414 | "\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21415 | " \"name_str\":\"%s\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21416 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21417 | ", \"entity_id\":\"%d\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21418 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21419 | "}\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21420 | (void *) prop, (void *) prop->next, prop->attributes | attrs, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21421 | prop->name, val_type(v7, prop->value), prop->value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21422 | v7_get_cstring(v7, &prop->name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21423 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21424 | , |
Marko Mikulicic |
0:c0ecb8bf28eb | 21425 | prop->entity_id |
Marko Mikulicic |
0:c0ecb8bf28eb | 21426 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21427 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21428 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21430 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21431 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 21432 | #line 1 "v7/src/parser.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21433 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21434 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21435 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 21436 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 21437 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21438 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21439 | /* Amalgamated: #include "common/coroutine.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21440 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21441 | /* Amalgamated: #include "v7/src/parser.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21442 | /* Amalgamated: #include "v7/src/tokenizer.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21443 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21444 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21445 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21446 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21447 | /* Amalgamated: #include "v7/src/cyg_profile.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21449 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21451 | #define ACCEPT(t) (((v7)->cur_tok == (t)) ? next_tok((v7)), 1 : 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21453 | #define EXPECT(t) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21454 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21455 | if ((v7)->cur_tok != (t)) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21456 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21457 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21458 | next_tok(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21459 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21461 | #define PARSE_WITH_OPT_ARG(tag, arg_tag, arg_parser, label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21462 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21463 | if (end_of_statement(v7) == V7_OK) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21464 | add_node(v7, a, (tag)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21465 | } else { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21466 | add_node(v7, a, (arg_tag)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21467 | arg_parser(label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21468 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21469 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21471 | #define N (CR_ARG_RET_PT()->arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21473 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21474 | * User functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 21475 | * (as well as other in-function entry points) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21476 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21477 | enum my_fid { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21478 | fid_none = CR_FID__NONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21480 | /* parse_script function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21481 | fid_parse_script = CR_FID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21482 | fid_p_script_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21483 | fid_p_script_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21484 | fid_p_script_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21485 | fid_p_script_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21486 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21487 | /* parse_use_strict function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21488 | fid_parse_use_strict, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21490 | /* parse_body function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21491 | fid_parse_body, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21492 | fid_p_body_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21493 | fid_p_body_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21494 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21495 | /* parse_statement function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21496 | fid_parse_statement, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21497 | fid_p_stat_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21498 | fid_p_stat_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21499 | fid_p_stat_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21500 | fid_p_stat_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21501 | fid_p_stat_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21502 | fid_p_stat_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21503 | fid_p_stat_7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21504 | fid_p_stat_8, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21505 | fid_p_stat_9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21506 | fid_p_stat_10, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21507 | fid_p_stat_11, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21508 | fid_p_stat_12, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21509 | fid_p_stat_13, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21510 | fid_p_stat_14, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21512 | /* parse_expression function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21513 | fid_parse_expression, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21514 | fid_p_expr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21515 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21516 | /* parse_assign function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21517 | fid_parse_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21518 | fid_p_assign_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21519 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21520 | /* parse_binary function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21521 | fid_parse_binary, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21522 | fid_p_binary_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21523 | fid_p_binary_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21524 | fid_p_binary_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21525 | fid_p_binary_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21526 | fid_p_binary_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21527 | fid_p_binary_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21529 | /* parse_prefix function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21530 | fid_parse_prefix, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21531 | fid_p_prefix_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21533 | /* parse_postfix function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21534 | fid_parse_postfix, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21535 | fid_p_postfix_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21537 | /* parse_callexpr function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21538 | fid_parse_callexpr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21539 | fid_p_callexpr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21540 | fid_p_callexpr_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21541 | fid_p_callexpr_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21542 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21543 | /* parse_newexpr function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21544 | fid_parse_newexpr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21545 | fid_p_newexpr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21546 | fid_p_newexpr_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21547 | fid_p_newexpr_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21548 | fid_p_newexpr_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21549 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21550 | /* parse_terminal function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21551 | fid_parse_terminal, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21552 | fid_p_terminal_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21553 | fid_p_terminal_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21554 | fid_p_terminal_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21555 | fid_p_terminal_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21557 | /* parse_block function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21558 | fid_parse_block, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21559 | fid_p_block_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21561 | /* parse_if function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21562 | fid_parse_if, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21563 | fid_p_if_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21564 | fid_p_if_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21565 | fid_p_if_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21567 | /* parse_while function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21568 | fid_parse_while, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21569 | fid_p_while_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21570 | fid_p_while_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21572 | /* parse_ident function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21573 | fid_parse_ident, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21575 | /* parse_ident_allow_reserved_words function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21576 | fid_parse_ident_allow_reserved_words, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21577 | fid_p_ident_arw_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21578 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21579 | /* parse_funcdecl function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21580 | fid_parse_funcdecl, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21581 | fid_p_funcdecl_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21582 | fid_p_funcdecl_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21583 | fid_p_funcdecl_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21584 | fid_p_funcdecl_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21585 | fid_p_funcdecl_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21586 | fid_p_funcdecl_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21587 | fid_p_funcdecl_7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21588 | fid_p_funcdecl_8, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21589 | fid_p_funcdecl_9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21591 | /* parse_arglist function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21592 | fid_parse_arglist, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21593 | fid_p_arglist_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21594 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21595 | /* parse_member function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21596 | fid_parse_member, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21597 | fid_p_member_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21599 | /* parse_memberexpr function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21600 | fid_parse_memberexpr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21601 | fid_p_memberexpr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21602 | fid_p_memberexpr_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21604 | /* parse_var function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21605 | fid_parse_var, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21606 | fid_p_var_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21607 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21608 | /* parse_prop function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21609 | fid_parse_prop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21610 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 21611 | fid_p_prop_1_getter, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21612 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21613 | fid_p_prop_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21614 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 21615 | fid_p_prop_3_setter, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21616 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21617 | fid_p_prop_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21618 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21619 | /* parse_dowhile function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21620 | fid_parse_dowhile, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21621 | fid_p_dowhile_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21622 | fid_p_dowhile_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21624 | /* parse_for function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21625 | fid_parse_for, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21626 | fid_p_for_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21627 | fid_p_for_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21628 | fid_p_for_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21629 | fid_p_for_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21630 | fid_p_for_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21631 | fid_p_for_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21633 | /* parse_try function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21634 | fid_parse_try, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21635 | fid_p_try_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21636 | fid_p_try_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21637 | fid_p_try_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21638 | fid_p_try_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21640 | /* parse_switch function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21641 | fid_parse_switch, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21642 | fid_p_switch_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21643 | fid_p_switch_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21644 | fid_p_switch_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21645 | fid_p_switch_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21646 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21647 | /* parse_with function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21648 | fid_parse_with, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21649 | fid_p_with_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21650 | fid_p_with_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21652 | MY_FID_CNT |
Marko Mikulicic |
0:c0ecb8bf28eb | 21653 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21655 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21656 | * User exception IDs. The first one should have value `CR_EXC_ID__USER` |
Marko Mikulicic |
0:c0ecb8bf28eb | 21657 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21658 | enum parser_exc_id { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21659 | PARSER_EXC_ID__NONE = CR_EXC_ID__NONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21660 | PARSER_EXC_ID__SYNTAX_ERROR = CR_EXC_ID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21661 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21663 | /* structures with locals and args {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21664 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21665 | /* parse_script {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21667 | /* parse_script's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21668 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21669 | typedef struct fid_parse_script_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21670 | } fid_parse_script_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21671 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21672 | typedef cr_zero_size_type_t fid_parse_script_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21673 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21675 | /* parse_script's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21676 | typedef struct fid_parse_script_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21677 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21678 | struct fid_parse_script_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21679 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21680 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21681 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21682 | ast_off_t outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21683 | int saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21684 | } fid_parse_script_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21686 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21687 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21688 | /* parse_use_strict {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21689 | /* parse_use_strict's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21690 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21691 | typedef struct fid_parse_use_strict_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21692 | } fid_parse_use_strict_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21693 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21694 | typedef cr_zero_size_type_t fid_parse_use_strict_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21695 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21697 | /* parse_use_strict's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21698 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21699 | typedef struct fid_parse_use_strict_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21700 | struct fid_parse_use_strict_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21701 | } fid_parse_use_strict_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21702 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21703 | typedef cr_zero_size_type_t fid_parse_use_strict_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21704 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21706 | #define CALL_PARSE_USE_STRICT(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21707 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21708 | CR_CALL(fid_parse_use_strict, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21709 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21711 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21713 | /* parse_body {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21714 | /* parse_body's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21715 | typedef struct fid_parse_body_arg { enum v7_tok end; } fid_parse_body_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21716 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21717 | /* parse_body's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21718 | typedef struct fid_parse_body_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21719 | struct fid_parse_body_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21721 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21722 | } fid_parse_body_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21723 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21724 | #define CALL_PARSE_BODY(_end, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21725 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21726 | N.fid_parse_body.end = (_end); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21727 | CR_CALL(fid_parse_body, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21728 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21729 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21730 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21731 | /* parse_statement {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21732 | /* parse_statement's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21733 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21734 | typedef struct fid_parse_statement_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21735 | } fid_parse_statement_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21736 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21737 | typedef cr_zero_size_type_t fid_parse_statement_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21738 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21739 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21740 | /* parse_statement's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21741 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21742 | typedef struct fid_parse_statement_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21743 | struct fid_parse_statement_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21744 | } fid_parse_statement_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21745 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21746 | typedef cr_zero_size_type_t fid_parse_statement_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21747 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21749 | #define CALL_PARSE_STATEMENT(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21750 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21751 | CR_CALL(fid_parse_statement, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21752 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21753 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21754 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21755 | /* parse_expression {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21756 | /* parse_expression's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21757 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21758 | typedef struct fid_parse_expression_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21759 | } fid_parse_expression_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21760 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21761 | typedef cr_zero_size_type_t fid_parse_expression_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21762 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21764 | /* parse_expression's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21765 | typedef struct fid_parse_expression_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21766 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21767 | struct fid_parse_expression_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21768 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21770 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21771 | int group; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21772 | } fid_parse_expression_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21773 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21774 | #define CALL_PARSE_EXPRESSION(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21775 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21776 | CR_CALL(fid_parse_expression, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21777 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21778 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21780 | /* parse_assign {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21781 | /* parse_assign's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21782 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21783 | typedef struct fid_parse_assign_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21784 | } fid_parse_assign_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21785 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21786 | typedef cr_zero_size_type_t fid_parse_assign_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21787 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21789 | /* parse_assign's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21790 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21791 | typedef struct fid_parse_assign_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21792 | struct fid_parse_assign_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21793 | } fid_parse_assign_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21794 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21795 | typedef cr_zero_size_type_t fid_parse_assign_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21796 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21798 | #define CALL_PARSE_ASSIGN(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21799 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21800 | CR_CALL(fid_parse_assign, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21801 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21802 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21804 | /* parse_binary {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21805 | /* parse_binary's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21806 | typedef struct fid_parse_binary_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21807 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21808 | uint8_t min_level; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21809 | } fid_parse_binary_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21811 | /* parse_binary's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21812 | typedef struct fid_parse_binary_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21813 | struct fid_parse_binary_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21815 | uint8_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21816 | /* during iteration, it becomes negative, so should be signed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21817 | int8_t level; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21818 | uint8_t /*enum v7_tok*/ tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21819 | uint8_t /*enum ast_tag*/ ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21820 | ast_off_t saved_mbuf_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21821 | } fid_parse_binary_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21823 | #define CALL_PARSE_BINARY(_level, _pos, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21824 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21825 | N.fid_parse_binary.min_level = (_level); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21826 | N.fid_parse_binary.pos = (_pos); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21827 | CR_CALL(fid_parse_binary, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21828 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21829 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21831 | /* parse_prefix {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21832 | /* parse_prefix's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21833 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21834 | typedef struct fid_parse_prefix_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21835 | } fid_parse_prefix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21836 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21837 | typedef cr_zero_size_type_t fid_parse_prefix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21838 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21840 | /* parse_prefix's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21841 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21842 | typedef struct fid_parse_prefix_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21843 | struct fid_parse_prefix_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21844 | } fid_parse_prefix_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21845 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21846 | typedef cr_zero_size_type_t fid_parse_prefix_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21847 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21849 | #define CALL_PARSE_PREFIX(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21850 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21851 | CR_CALL(fid_parse_prefix, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21852 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21853 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21855 | /* parse_postfix {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21856 | /* parse_postfix's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21857 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21858 | typedef struct fid_parse_postfix_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21859 | } fid_parse_postfix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21860 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21861 | typedef cr_zero_size_type_t fid_parse_postfix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21862 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21863 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21864 | /* parse_postfix's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21865 | typedef struct fid_parse_postfix_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21866 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21867 | struct fid_parse_postfix_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21868 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21869 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21870 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21871 | } fid_parse_postfix_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21873 | #define CALL_PARSE_POSTFIX(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21874 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21875 | CR_CALL(fid_parse_postfix, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21876 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21877 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21879 | /* parse_callexpr {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21880 | /* parse_callexpr's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21881 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21882 | typedef struct fid_parse_callexpr_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21883 | } fid_parse_callexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21884 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21885 | typedef cr_zero_size_type_t fid_parse_callexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21886 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21888 | /* parse_callexpr's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21889 | typedef struct fid_parse_callexpr_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21890 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21891 | struct fid_parse_callexpr_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21892 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21894 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21895 | } fid_parse_callexpr_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21897 | #define CALL_PARSE_CALLEXPR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21898 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21899 | CR_CALL(fid_parse_callexpr, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21900 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21901 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21903 | /* parse_newexpr {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21904 | /* parse_newexpr's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21905 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21906 | typedef struct fid_parse_newexpr_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21907 | } fid_parse_newexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21908 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21909 | typedef cr_zero_size_type_t fid_parse_newexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21910 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21912 | /* parse_newexpr's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21913 | typedef struct fid_parse_newexpr_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21914 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21915 | struct fid_parse_newexpr_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21916 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21918 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21919 | } fid_parse_newexpr_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21920 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21921 | #define CALL_PARSE_NEWEXPR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21922 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21923 | CR_CALL(fid_parse_newexpr, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21924 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21925 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21927 | /* parse_terminal {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21928 | /* parse_terminal's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21929 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21930 | typedef struct fid_parse_terminal_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21931 | } fid_parse_terminal_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21932 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21933 | typedef cr_zero_size_type_t fid_parse_terminal_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21934 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21936 | /* parse_terminal's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21937 | typedef struct fid_parse_terminal_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21938 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21939 | struct fid_parse_terminal_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21940 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21942 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21943 | } fid_parse_terminal_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21945 | #define CALL_PARSE_TERMINAL(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21946 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21947 | CR_CALL(fid_parse_terminal, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21948 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21949 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21950 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21951 | /* parse_block {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21952 | /* parse_block's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21953 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21954 | typedef struct fid_parse_block_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21955 | } fid_parse_block_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21956 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21957 | typedef cr_zero_size_type_t fid_parse_block_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21958 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21960 | /* parse_block's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21961 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21962 | typedef struct fid_parse_block_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21963 | struct fid_parse_block_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21964 | } fid_parse_block_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21965 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21966 | typedef cr_zero_size_type_t fid_parse_block_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21967 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21969 | #define CALL_PARSE_BLOCK(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21970 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21971 | CR_CALL(fid_parse_block, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21972 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21973 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21975 | /* parse_if {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21976 | /* parse_if's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21977 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21978 | typedef struct fid_parse_if_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21979 | } fid_parse_if_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21980 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21981 | typedef cr_zero_size_type_t fid_parse_if_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21982 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21984 | /* parse_if's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21985 | typedef struct fid_parse_if_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21986 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21987 | struct fid_parse_if_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21988 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21989 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21990 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21991 | } fid_parse_if_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21993 | #define CALL_PARSE_IF(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21994 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21995 | CR_CALL(fid_parse_if, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21996 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21997 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21999 | /* parse_while {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22000 | /* parse_while's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22001 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22002 | typedef struct fid_parse_while_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22003 | } fid_parse_while_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22004 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22005 | typedef cr_zero_size_type_t fid_parse_while_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22006 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22008 | /* parse_while's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22009 | typedef struct fid_parse_while_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22010 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22011 | struct fid_parse_while_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22012 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22014 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22015 | uint8_t saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22016 | } fid_parse_while_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22018 | #define CALL_PARSE_WHILE(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22019 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22020 | CR_CALL(fid_parse_while, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22021 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22022 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22024 | /* parse_ident {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22025 | /* parse_ident's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22026 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22027 | typedef struct fid_parse_ident_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22028 | } fid_parse_ident_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22029 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22030 | typedef cr_zero_size_type_t fid_parse_ident_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22031 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22033 | /* parse_ident's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22034 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22035 | typedef struct fid_parse_ident_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22036 | struct fid_parse_ident_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22037 | } fid_parse_ident_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22038 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22039 | typedef cr_zero_size_type_t fid_parse_ident_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22040 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22042 | #define CALL_PARSE_IDENT(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22043 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22044 | CR_CALL(fid_parse_ident, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22045 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22046 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22047 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22048 | /* parse_ident_allow_reserved_words {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22049 | /* parse_ident_allow_reserved_words's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22050 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22051 | typedef struct fid_parse_ident_allow_reserved_words_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22052 | } fid_parse_ident_allow_reserved_words_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22053 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22054 | typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22055 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22057 | /* parse_ident_allow_reserved_words's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22058 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22059 | typedef struct fid_parse_ident_allow_reserved_words_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22060 | struct fid_parse_ident_allow_reserved_words_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22061 | } fid_parse_ident_allow_reserved_words_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22062 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22063 | typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22064 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22066 | #define CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22067 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22068 | CR_CALL(fid_parse_ident_allow_reserved_words, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22069 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22070 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22072 | /* parse_funcdecl {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22073 | /* parse_funcdecl's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22074 | typedef struct fid_parse_funcdecl_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22075 | uint8_t require_named; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22076 | uint8_t reserved_name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22077 | } fid_parse_funcdecl_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22079 | /* parse_funcdecl's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22080 | typedef struct fid_parse_funcdecl_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22081 | struct fid_parse_funcdecl_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22083 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22084 | ast_off_t outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22085 | uint8_t saved_in_function; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22086 | uint8_t saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22087 | } fid_parse_funcdecl_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22088 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22089 | #define CALL_PARSE_FUNCDECL(_require_named, _reserved_name, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22090 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22091 | N.fid_parse_funcdecl.require_named = (_require_named); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22092 | N.fid_parse_funcdecl.reserved_name = (_reserved_name); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22093 | CR_CALL(fid_parse_funcdecl, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22094 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22095 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22097 | /* parse_arglist {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22098 | /* parse_arglist's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22099 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22100 | typedef struct fid_parse_arglist_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22101 | } fid_parse_arglist_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22102 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22103 | typedef cr_zero_size_type_t fid_parse_arglist_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22104 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22106 | /* parse_arglist's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22107 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22108 | typedef struct fid_parse_arglist_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22109 | struct fid_parse_arglist_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22110 | } fid_parse_arglist_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22111 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22112 | typedef cr_zero_size_type_t fid_parse_arglist_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22113 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22115 | #define CALL_PARSE_ARGLIST(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22116 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22117 | CR_CALL(fid_parse_arglist, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22118 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22119 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22121 | /* parse_member {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22122 | /* parse_member's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22123 | typedef struct fid_parse_member_arg { ast_off_t pos; } fid_parse_member_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22125 | /* parse_member's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22126 | typedef struct fid_parse_member_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22127 | struct fid_parse_member_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22128 | } fid_parse_member_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22129 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22130 | #define CALL_PARSE_MEMBER(_pos, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22131 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22132 | N.fid_parse_member.pos = (_pos); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22133 | CR_CALL(fid_parse_member, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22134 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22135 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22136 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22137 | /* parse_memberexpr {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22138 | /* parse_memberexpr's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22139 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22140 | typedef struct fid_parse_memberexpr_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22141 | } fid_parse_memberexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22142 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22143 | typedef cr_zero_size_type_t fid_parse_memberexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22144 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22146 | /* parse_memberexpr's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22147 | typedef struct fid_parse_memberexpr_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22148 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22149 | struct fid_parse_memberexpr_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22150 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22151 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22152 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22153 | } fid_parse_memberexpr_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22154 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22155 | #define CALL_PARSE_MEMBEREXPR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22156 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22157 | CR_CALL(fid_parse_memberexpr, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22158 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22159 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22161 | /* parse_var {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22162 | /* parse_var's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22163 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22164 | typedef struct fid_parse_var_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22165 | } fid_parse_var_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22166 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22167 | typedef cr_zero_size_type_t fid_parse_var_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22168 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22170 | /* parse_var's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22171 | typedef struct fid_parse_var_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22172 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22173 | struct fid_parse_var_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22174 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22175 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22176 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22177 | } fid_parse_var_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22178 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22179 | #define CALL_PARSE_VAR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22180 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22181 | CR_CALL(fid_parse_var, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22182 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22183 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22185 | /* parse_prop {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22186 | /* parse_prop's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22187 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22188 | typedef struct fid_parse_prop_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22189 | } fid_parse_prop_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22190 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22191 | typedef cr_zero_size_type_t fid_parse_prop_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22192 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22194 | /* parse_prop's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22195 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22196 | typedef struct fid_parse_prop_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22197 | struct fid_parse_prop_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22198 | } fid_parse_prop_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22199 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22200 | typedef cr_zero_size_type_t fid_parse_prop_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22201 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22203 | #define CALL_PARSE_PROP(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22204 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22205 | CR_CALL(fid_parse_prop, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22206 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22207 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22209 | /* parse_dowhile {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22210 | /* parse_dowhile's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22211 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22212 | typedef struct fid_parse_dowhile_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22213 | } fid_parse_dowhile_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22214 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22215 | typedef cr_zero_size_type_t fid_parse_dowhile_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22216 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22218 | /* parse_dowhile's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22219 | typedef struct fid_parse_dowhile_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22220 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22221 | struct fid_parse_dowhile_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22222 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22223 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22224 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22225 | uint8_t saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22226 | } fid_parse_dowhile_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22228 | #define CALL_PARSE_DOWHILE(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22229 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22230 | CR_CALL(fid_parse_dowhile, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22231 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22232 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22233 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22234 | /* parse_for {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22235 | /* parse_for's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22236 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22237 | typedef struct fid_parse_for_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22238 | } fid_parse_for_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22239 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22240 | typedef cr_zero_size_type_t fid_parse_for_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22241 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22243 | /* parse_for's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22244 | typedef struct fid_parse_for_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22245 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22246 | struct fid_parse_for_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22247 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22249 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22250 | uint8_t saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22251 | } fid_parse_for_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22253 | #define CALL_PARSE_FOR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22254 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22255 | CR_CALL(fid_parse_for, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22256 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22257 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22258 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22259 | /* parse_try {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22260 | /* parse_try's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22261 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22262 | typedef struct fid_parse_try_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22263 | } fid_parse_try_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22264 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22265 | typedef cr_zero_size_type_t fid_parse_try_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22266 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22268 | /* parse_try's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22269 | typedef struct fid_parse_try_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22270 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22271 | struct fid_parse_try_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22272 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22274 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22275 | uint8_t catch_or_finally; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22276 | } fid_parse_try_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22278 | #define CALL_PARSE_TRY(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22279 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22280 | CR_CALL(fid_parse_try, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22281 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22282 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22284 | /* parse_switch {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22285 | /* parse_switch's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22286 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22287 | typedef struct fid_parse_switch_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22288 | } fid_parse_switch_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22289 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22290 | typedef cr_zero_size_type_t fid_parse_switch_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22291 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22293 | /* parse_switch's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22294 | typedef struct fid_parse_switch_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22295 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22296 | struct fid_parse_switch_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22297 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22299 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22300 | int saved_in_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22301 | ast_off_t case_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22302 | } fid_parse_switch_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22303 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22304 | #define CALL_PARSE_SWITCH(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22305 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22306 | CR_CALL(fid_parse_switch, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22307 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22308 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22309 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22310 | /* parse_with {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22311 | /* parse_with's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22312 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22313 | typedef struct fid_parse_with_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22314 | } fid_parse_with_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22315 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22316 | typedef cr_zero_size_type_t fid_parse_with_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22317 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22319 | /* parse_with's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22320 | typedef struct fid_parse_with_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22321 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22322 | struct fid_parse_with_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22323 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22324 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22325 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22326 | } fid_parse_with_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22328 | #define CALL_PARSE_WITH(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22329 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22330 | CR_CALL(fid_parse_with, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22331 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22332 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22334 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22336 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22337 | * Array of "function" descriptors. Each descriptor contains just a size |
Marko Mikulicic |
0:c0ecb8bf28eb | 22338 | * of "function"'s locals. |
Marko Mikulicic |
0:c0ecb8bf28eb | 22339 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22340 | static const struct cr_func_desc _fid_descrs[MY_FID_CNT] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22342 | /* fid_none */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22343 | {0}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22345 | /* fid_parse_script ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22346 | /* fid_parse_script */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22347 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22348 | /* fid_p_script_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22349 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22350 | /* fid_p_script_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22351 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22352 | /* fid_p_script_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22353 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22354 | /* fid_p_script_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22355 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22357 | /* fid_parse_use_strict ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22358 | /* fid_parse_use_strict */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22359 | {CR_LOCALS_SIZEOF(fid_parse_use_strict_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22361 | /* fid_parse_body ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22362 | /* fid_parse_body */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22363 | {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22364 | /* fid_p_body_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22365 | {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22366 | /* fid_p_body_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22367 | {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22369 | /* fid_parse_statement ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22370 | /* fid_parse_statement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22371 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22372 | /* fid_p_stat_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22373 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22374 | /* fid_p_stat_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22375 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22376 | /* fid_p_stat_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22377 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22378 | /* fid_p_stat_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22379 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22380 | /* fid_p_stat_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22381 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22382 | /* fid_p_stat_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22383 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22384 | /* fid_p_stat_7 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22385 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22386 | /* fid_p_stat_8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22387 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22388 | /* fid_p_stat_9 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22389 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22390 | /* fid_p_stat_10 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22391 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22392 | /* fid_p_stat_11 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22393 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22394 | /* fid_p_stat_12 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22395 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22396 | /* fid_p_stat_13 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22397 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22398 | /* fid_p_stat_14 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22399 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22400 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22401 | /* fid_parse_expression ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22402 | /* fid_parse_expression */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22403 | {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22404 | /* fid_p_expr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22405 | {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22406 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22407 | /* fid_parse_assign ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22408 | /* fid_parse_assign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22409 | {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22410 | /* fid_p_assign_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22411 | {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22413 | /* fid_parse_binary ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22414 | /* fid_parse_binary */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22415 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22416 | /* fid_p_binary_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22417 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22418 | /* fid_p_binary_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22419 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22420 | /* fid_p_binary_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22421 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22422 | /* fid_p_binary_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22423 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22424 | /* fid_p_binary_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22425 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22426 | /* fid_p_binary_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22427 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22429 | /* fid_parse_prefix ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22430 | /* fid_parse_prefix */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22431 | {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22432 | /* fid_p_prefix_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22433 | {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22434 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22435 | /* fid_parse_postfix ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22436 | /* fid_parse_postfix */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22437 | {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22438 | /* fid_p_postfix_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22439 | {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22441 | /* fid_parse_callexpr ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22442 | /* fid_parse_callexpr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22443 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22444 | /* fid_p_callexpr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22445 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22446 | /* fid_p_callexpr_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22447 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22448 | /* fid_p_callexpr_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22449 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22451 | /* fid_parse_newexpr ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22452 | /* fid_parse_newexpr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22453 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22454 | /* fid_p_newexpr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22455 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22456 | /* fid_p_newexpr_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22457 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22458 | /* fid_p_newexpr_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22459 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22460 | /* fid_p_newexpr_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22461 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22463 | /* fid_parse_terminal ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22464 | /* fid_parse_terminal */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22465 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22466 | /* fid_p_terminal_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22467 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22468 | /* fid_p_terminal_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22469 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22470 | /* fid_p_terminal_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22471 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22472 | /* fid_p_terminal_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22473 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22475 | /* fid_parse_block ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22476 | /* fid_parse_block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22477 | {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22478 | /* fid_p_block_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22479 | {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22481 | /* fid_parse_if ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22482 | /* fid_parse_if */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22483 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22484 | /* fid_p_if_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22485 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22486 | /* fid_p_if_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22487 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22488 | /* fid_p_if_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22489 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22491 | /* fid_parse_while ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22492 | /* fid_parse_while */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22493 | {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22494 | /* fid_p_while_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22495 | {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22496 | /* fid_p_while_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22497 | {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22499 | /* fid_parse_ident ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22500 | /* fid_parse_ident */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22501 | {CR_LOCALS_SIZEOF(fid_parse_ident_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22502 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22503 | /* fid_parse_ident_allow_reserved_words -------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22504 | /* fid_parse_ident_allow_reserved_words */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22505 | {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22506 | /* fid_p_ident_allow_reserved_words_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22507 | {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22509 | /* fid_parse_funcdecl ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22510 | /* fid_parse_funcdecl */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22511 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22512 | /* fid_p_funcdecl_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22513 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22514 | /* fid_p_funcdecl_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22515 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22516 | /* fid_p_funcdecl_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22517 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22518 | /* fid_p_funcdecl_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22519 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22520 | /* fid_p_funcdecl_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22521 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22522 | /* fid_p_funcdecl_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22523 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22524 | /* fid_p_funcdecl_7 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22525 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22526 | /* fid_p_funcdecl_8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22527 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22528 | /* fid_p_funcdecl_9 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22529 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22531 | /* fid_parse_arglist ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22532 | /* fid_parse_arglist */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22533 | {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22534 | /* fid_p_arglist_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22535 | {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22537 | /* fid_parse_member ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22538 | /* fid_parse_member */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22539 | {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22540 | /* fid_p_member_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22541 | {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22542 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22543 | /* fid_parse_memberexpr ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22544 | /* fid_parse_memberexpr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22545 | {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22546 | /* fid_p_memberexpr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22547 | {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22548 | /* fid_p_memberexpr_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22549 | {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22550 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22551 | /* fid_parse_var ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22552 | /* fid_parse_var */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22553 | {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22554 | /* fid_p_var_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22555 | {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22557 | /* fid_parse_prop ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22558 | /* fid_parse_prop */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22559 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22560 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22561 | /* fid_p_prop_1_getter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22562 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22563 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22564 | /* fid_p_prop_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22565 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22566 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22567 | /* fid_p_prop_3_setter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22568 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22569 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22570 | /* fid_p_prop_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22571 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22573 | /* fid_parse_dowhile ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22574 | /* fid_parse_dowhile */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22575 | {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22576 | /* fid_p_dowhile_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22577 | {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22578 | /* fid_p_dowhile_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22579 | {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22581 | /* fid_parse_for ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22582 | /* fid_parse_for */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22583 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22584 | /* fid_p_for_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22585 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22586 | /* fid_p_for_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22587 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22588 | /* fid_p_for_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22589 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22590 | /* fid_p_for_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22591 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22592 | /* fid_p_for_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22593 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22594 | /* fid_p_for_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22595 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22597 | /* fid_parse_try ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22598 | /* fid_parse_try */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22599 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22600 | /* fid_p_try_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22601 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22602 | /* fid_p_try_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22603 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22604 | /* fid_p_try_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22605 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22606 | /* fid_p_try_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22607 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22608 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22609 | /* fid_parse_switch ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22610 | /* fid_parse_switch */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22611 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22612 | /* fid_p_switch_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22613 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22614 | /* fid_p_switch_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22615 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22616 | /* fid_p_switch_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22617 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22618 | /* fid_p_switch_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22619 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22621 | /* fid_parse_with ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22622 | /* fid_parse_with */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22623 | {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22624 | /* fid_p_with_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22625 | {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22626 | /* fid_p_with_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22627 | {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22628 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22629 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22630 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22631 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22632 | * Union of arguments and return values for all existing "functions". |
Marko Mikulicic |
0:c0ecb8bf28eb | 22633 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 22634 | * Used as an accumulator when we call function, return from function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22635 | * yield, or resume. |
Marko Mikulicic |
0:c0ecb8bf28eb | 22636 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22637 | union user_arg_ret { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22638 | /* arguments to the next function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22639 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22640 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22641 | fid_parse_script_arg_t fid_parse_script; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22642 | fid_parse_use_strict_arg_t fid_parse_use_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22643 | fid_parse_statement_arg_t fid_parse_statement; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22644 | fid_parse_expression_arg_t fid_parse_expression; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22645 | fid_parse_assign_arg_t fid_parse_assign; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22646 | fid_parse_prefix_arg_t fid_parse_prefix; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22647 | fid_parse_postfix_arg_t fid_parse_postfix; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22648 | fid_parse_callexpr_arg_t fid_parse_callexpr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22649 | fid_parse_newexpr_arg_t fid_parse_newexpr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22650 | fid_parse_terminal_arg_t fid_parse_terminal; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22651 | fid_parse_block_arg_t fid_parse_block; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22652 | fid_parse_if_arg_t fid_parse_if; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22653 | fid_parse_while_arg_t fid_parse_while; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22654 | fid_parse_ident_arg_t fid_parse_ident; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22655 | fid_parse_ident_allow_reserved_words_arg_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 22656 | fid_parse_ident_allow_reserved_words; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22657 | fid_parse_arglist_arg_t fid_parse_arglist; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22658 | fid_parse_memberexpr_arg_t fid_parse_memberexpr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22659 | fid_parse_var_arg_t fid_parse_var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22660 | fid_parse_prop_arg_t fid_parse_prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22661 | fid_parse_dowhile_arg_t fid_parse_dowhile; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22662 | fid_parse_for_arg_t fid_parse_for; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22663 | fid_parse_try_arg_t fid_parse_try; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22664 | fid_parse_switch_arg_t fid_parse_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22665 | fid_parse_with_arg_t fid_parse_with; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22666 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22667 | fid_parse_body_arg_t fid_parse_body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22668 | fid_parse_binary_arg_t fid_parse_binary; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22669 | fid_parse_funcdecl_arg_t fid_parse_funcdecl; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22670 | fid_parse_member_arg_t fid_parse_member; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22671 | } arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22673 | /* value returned from function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22674 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22675 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22676 | } ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22677 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22678 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22680 | static enum v7_tok next_tok(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22681 | int prev_line_no = v7->pstate.prev_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22682 | v7->pstate.prev_line_no = v7->pstate.line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22683 | v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22684 | v7->after_newline = prev_line_no != v7->pstate.line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22685 | v7->tok = v7->pstate.pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22686 | v7->cur_tok = get_tok(&v7->pstate.pc, v7->pstate.src_end, &v7->cur_tok_dbl, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22687 | v7->cur_tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22688 | v7->tok_len = v7->pstate.pc - v7->tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22689 | v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22690 | return v7->cur_tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22691 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22693 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22694 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22695 | * Assumes `offset` points to the byte right after a tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 22696 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22697 | static void insert_line_no_if_changed(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22698 | ast_off_t offset) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22699 | if (v7->pstate.prev_line_no != v7->line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22700 | v7->line_no = v7->pstate.prev_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22701 | ast_add_line_no(a, offset - 1, v7->line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22702 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22703 | #if V7_AST_FORCE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22704 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22705 | * This mode is needed for debug only: to make sure AST consumers correctly |
Marko Mikulicic |
0:c0ecb8bf28eb | 22706 | * consume all nodes with line numbers data encoded |
Marko Mikulicic |
0:c0ecb8bf28eb | 22707 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22708 | ast_add_line_no(a, offset - 1, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22709 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22710 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22711 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22712 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22713 | static void insert_line_no_if_changed(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22714 | ast_off_t offset) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22715 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22716 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22717 | (void) offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22718 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22719 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22721 | static ast_off_t insert_node(struct v7 *v7, struct ast *a, ast_off_t start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22722 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22723 | ast_off_t ret = ast_insert_node(a, start, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22724 | insert_line_no_if_changed(v7, a, ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22725 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22726 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22727 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22728 | static ast_off_t add_node(struct v7 *v7, struct ast *a, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22729 | return insert_node(v7, a, a->mbuf.len, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22732 | static ast_off_t insert_inlined_node(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22733 | ast_off_t start, enum ast_tag tag, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22734 | const char *name, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22735 | ast_off_t ret = ast_insert_inlined_node(a, start, tag, name, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22736 | insert_line_no_if_changed(v7, a, ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22737 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22738 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22739 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22740 | static ast_off_t add_inlined_node(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22741 | enum ast_tag tag, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22742 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22743 | return insert_inlined_node(v7, a, a->mbuf.len, tag, name, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22744 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22746 | static unsigned long get_column(const char *code, const char *pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22747 | const char *p = pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22748 | while (p > code && *p != '\n') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22749 | p--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22750 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22751 | return p == code ? pos - p : pos - (p + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22752 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22754 | static enum v7_err end_of_statement(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22755 | if (v7->cur_tok == TOK_SEMICOLON || v7->cur_tok == TOK_END_OF_INPUT || |
Marko Mikulicic |
0:c0ecb8bf28eb | 22756 | v7->cur_tok == TOK_CLOSE_CURLY || v7->after_newline) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22757 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22758 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22759 | return V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22760 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22761 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22762 | static enum v7_tok lookahead(const struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22763 | const char *s = v7->pstate.pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22764 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22765 | return get_tok(&s, v7->pstate.src_end, &d, v7->cur_tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22768 | static int parse_optional(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22769 | enum v7_tok terminator) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22770 | if (v7->cur_tok != terminator) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22771 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22772 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22773 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22774 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22775 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22777 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22778 | * On ESP8266 'levels' declaration have to be outside of 'parse_binary' |
Marko Mikulicic |
0:c0ecb8bf28eb | 22779 | * in order to prevent reboot on return from this function |
Marko Mikulicic |
0:c0ecb8bf28eb | 22780 | * TODO(alashkin): understand why |
Marko Mikulicic |
0:c0ecb8bf28eb | 22781 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22782 | #define NONE \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22783 | { (enum v7_tok) 0, (enum v7_tok) 0, (enum ast_tag) 0 } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22785 | static const struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22786 | int len, left_to_right; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22787 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22788 | enum v7_tok start_tok, end_tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22789 | enum ast_tag start_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22790 | } parts[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22791 | } levels[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22792 | {1, 0, {{TOK_ASSIGN, TOK_URSHIFT_ASSIGN, AST_ASSIGN}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22793 | {1, 0, {{TOK_QUESTION, TOK_QUESTION, AST_COND}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22794 | {1, 1, {{TOK_LOGICAL_OR, TOK_LOGICAL_OR, AST_LOGICAL_OR}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22795 | {1, 1, {{TOK_LOGICAL_AND, TOK_LOGICAL_AND, AST_LOGICAL_AND}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22796 | {1, 1, {{TOK_OR, TOK_OR, AST_OR}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22797 | {1, 1, {{TOK_XOR, TOK_XOR, AST_XOR}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22798 | {1, 1, {{TOK_AND, TOK_AND, AST_AND}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22799 | {1, 1, {{TOK_EQ, TOK_NE_NE, AST_EQ}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22800 | {2, 1, {{TOK_LE, TOK_GT, AST_LE}, {TOK_IN, TOK_INSTANCEOF, AST_IN}}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22801 | {1, 1, {{TOK_LSHIFT, TOK_URSHIFT, AST_LSHIFT}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22802 | {1, 1, {{TOK_PLUS, TOK_MINUS, AST_ADD}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22803 | {1, 1, {{TOK_REM, TOK_DIV, AST_REM}, NONE}}}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22804 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22805 | enum cr_status parser_cr_exec(struct cr_ctx *p_ctx, struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22806 | struct ast *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22807 | enum cr_status rc = CR_RES__OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22809 | _cr_iter_begin: |
Marko Mikulicic |
0:c0ecb8bf28eb | 22810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22811 | rc = cr_on_iter_begin(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22812 | if (rc != CR_RES__OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22813 | return rc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22816 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22817 | * dispatcher switch: depending on the fid, jump to the corresponding label |
Marko Mikulicic |
0:c0ecb8bf28eb | 22818 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22819 | switch ((enum my_fid) CR_CURR_FUNC()) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22820 | CR_DEFINE_ENTRY_POINT(fid_none); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22821 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22822 | CR_DEFINE_ENTRY_POINT(fid_parse_script); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22823 | CR_DEFINE_ENTRY_POINT(fid_p_script_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22824 | CR_DEFINE_ENTRY_POINT(fid_p_script_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22825 | CR_DEFINE_ENTRY_POINT(fid_p_script_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22826 | CR_DEFINE_ENTRY_POINT(fid_p_script_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22828 | CR_DEFINE_ENTRY_POINT(fid_parse_use_strict); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22830 | CR_DEFINE_ENTRY_POINT(fid_parse_body); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22831 | CR_DEFINE_ENTRY_POINT(fid_p_body_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22832 | CR_DEFINE_ENTRY_POINT(fid_p_body_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22834 | CR_DEFINE_ENTRY_POINT(fid_parse_statement); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22835 | CR_DEFINE_ENTRY_POINT(fid_p_stat_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22836 | CR_DEFINE_ENTRY_POINT(fid_p_stat_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22837 | CR_DEFINE_ENTRY_POINT(fid_p_stat_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22838 | CR_DEFINE_ENTRY_POINT(fid_p_stat_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22839 | CR_DEFINE_ENTRY_POINT(fid_p_stat_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22840 | CR_DEFINE_ENTRY_POINT(fid_p_stat_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22841 | CR_DEFINE_ENTRY_POINT(fid_p_stat_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22842 | CR_DEFINE_ENTRY_POINT(fid_p_stat_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22843 | CR_DEFINE_ENTRY_POINT(fid_p_stat_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22844 | CR_DEFINE_ENTRY_POINT(fid_p_stat_10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22845 | CR_DEFINE_ENTRY_POINT(fid_p_stat_11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22846 | CR_DEFINE_ENTRY_POINT(fid_p_stat_12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22847 | CR_DEFINE_ENTRY_POINT(fid_p_stat_13); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22848 | CR_DEFINE_ENTRY_POINT(fid_p_stat_14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22850 | CR_DEFINE_ENTRY_POINT(fid_parse_expression); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22851 | CR_DEFINE_ENTRY_POINT(fid_p_expr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22853 | CR_DEFINE_ENTRY_POINT(fid_parse_assign); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22854 | CR_DEFINE_ENTRY_POINT(fid_p_assign_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22855 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22856 | CR_DEFINE_ENTRY_POINT(fid_parse_binary); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22857 | CR_DEFINE_ENTRY_POINT(fid_p_binary_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22858 | CR_DEFINE_ENTRY_POINT(fid_p_binary_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22859 | CR_DEFINE_ENTRY_POINT(fid_p_binary_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22860 | CR_DEFINE_ENTRY_POINT(fid_p_binary_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22861 | CR_DEFINE_ENTRY_POINT(fid_p_binary_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22863 | CR_DEFINE_ENTRY_POINT(fid_parse_prefix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22864 | CR_DEFINE_ENTRY_POINT(fid_p_prefix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22866 | CR_DEFINE_ENTRY_POINT(fid_parse_postfix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22867 | CR_DEFINE_ENTRY_POINT(fid_p_postfix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22869 | CR_DEFINE_ENTRY_POINT(fid_parse_callexpr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22870 | CR_DEFINE_ENTRY_POINT(fid_p_callexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22871 | CR_DEFINE_ENTRY_POINT(fid_p_callexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22872 | CR_DEFINE_ENTRY_POINT(fid_p_callexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22874 | CR_DEFINE_ENTRY_POINT(fid_parse_newexpr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22875 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22876 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22877 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22878 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22880 | CR_DEFINE_ENTRY_POINT(fid_parse_terminal); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22881 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22882 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22883 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22884 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22886 | CR_DEFINE_ENTRY_POINT(fid_parse_block); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22887 | CR_DEFINE_ENTRY_POINT(fid_p_block_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22889 | CR_DEFINE_ENTRY_POINT(fid_parse_if); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22890 | CR_DEFINE_ENTRY_POINT(fid_p_if_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22891 | CR_DEFINE_ENTRY_POINT(fid_p_if_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22892 | CR_DEFINE_ENTRY_POINT(fid_p_if_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22894 | CR_DEFINE_ENTRY_POINT(fid_parse_while); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22895 | CR_DEFINE_ENTRY_POINT(fid_p_while_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22896 | CR_DEFINE_ENTRY_POINT(fid_p_while_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22898 | CR_DEFINE_ENTRY_POINT(fid_parse_ident); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22899 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22900 | CR_DEFINE_ENTRY_POINT(fid_parse_ident_allow_reserved_words); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22901 | CR_DEFINE_ENTRY_POINT(fid_p_ident_arw_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22903 | CR_DEFINE_ENTRY_POINT(fid_parse_funcdecl); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22904 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22905 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22906 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22907 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22908 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22909 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22910 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22911 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22912 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22913 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22914 | CR_DEFINE_ENTRY_POINT(fid_parse_arglist); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22915 | CR_DEFINE_ENTRY_POINT(fid_p_arglist_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22917 | CR_DEFINE_ENTRY_POINT(fid_parse_member); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22918 | CR_DEFINE_ENTRY_POINT(fid_p_member_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22920 | CR_DEFINE_ENTRY_POINT(fid_parse_memberexpr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22921 | CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22922 | CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22924 | CR_DEFINE_ENTRY_POINT(fid_parse_var); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22925 | CR_DEFINE_ENTRY_POINT(fid_p_var_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22927 | CR_DEFINE_ENTRY_POINT(fid_parse_prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22928 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22929 | CR_DEFINE_ENTRY_POINT(fid_p_prop_1_getter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22930 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22931 | CR_DEFINE_ENTRY_POINT(fid_p_prop_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22932 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22933 | CR_DEFINE_ENTRY_POINT(fid_p_prop_3_setter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22934 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22935 | CR_DEFINE_ENTRY_POINT(fid_p_prop_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22937 | CR_DEFINE_ENTRY_POINT(fid_parse_dowhile); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22938 | CR_DEFINE_ENTRY_POINT(fid_p_dowhile_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22939 | CR_DEFINE_ENTRY_POINT(fid_p_dowhile_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22941 | CR_DEFINE_ENTRY_POINT(fid_parse_for); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22942 | CR_DEFINE_ENTRY_POINT(fid_p_for_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22943 | CR_DEFINE_ENTRY_POINT(fid_p_for_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22944 | CR_DEFINE_ENTRY_POINT(fid_p_for_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22945 | CR_DEFINE_ENTRY_POINT(fid_p_for_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22946 | CR_DEFINE_ENTRY_POINT(fid_p_for_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22947 | CR_DEFINE_ENTRY_POINT(fid_p_for_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22948 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22949 | CR_DEFINE_ENTRY_POINT(fid_parse_try); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22950 | CR_DEFINE_ENTRY_POINT(fid_p_try_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22951 | CR_DEFINE_ENTRY_POINT(fid_p_try_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22952 | CR_DEFINE_ENTRY_POINT(fid_p_try_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22953 | CR_DEFINE_ENTRY_POINT(fid_p_try_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22955 | CR_DEFINE_ENTRY_POINT(fid_parse_switch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22956 | CR_DEFINE_ENTRY_POINT(fid_p_switch_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22957 | CR_DEFINE_ENTRY_POINT(fid_p_switch_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22958 | CR_DEFINE_ENTRY_POINT(fid_p_switch_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22959 | CR_DEFINE_ENTRY_POINT(fid_p_switch_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22961 | CR_DEFINE_ENTRY_POINT(fid_parse_with); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22962 | CR_DEFINE_ENTRY_POINT(fid_p_with_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22963 | CR_DEFINE_ENTRY_POINT(fid_p_with_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22964 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22965 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 22966 | /* should never be here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22967 | printf("fatal: wrong func id: %d", CR_CURR_FUNC()); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22968 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22969 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22971 | /* static enum v7_err parse_script(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22972 | fid_parse_script : |
Marko Mikulicic |
0:c0ecb8bf28eb | 22973 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 22974 | #define L CR_CUR_LOCALS_PT(fid_parse_script_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22975 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22976 | L->start = add_node(v7, a, AST_SCRIPT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22977 | L->outer_last_var_node = v7->last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22978 | L->saved_in_strict = v7->pstate.in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22980 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22981 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22983 | CR_TRY(fid_p_script_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22984 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22985 | CALL_PARSE_USE_STRICT(fid_p_script_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22986 | v7->pstate.in_strict = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22987 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22988 | CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_script_1, fid_p_script_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22989 | CR_ENDCATCH(fid_p_script_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22991 | CALL_PARSE_BODY(TOK_END_OF_INPUT, fid_p_script_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22992 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22993 | v7->pstate.in_strict = L->saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22994 | v7->last_var_node = L->outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22996 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22997 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22999 | /* static enum v7_err parse_use_strict(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23000 | fid_parse_use_strict : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23001 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23002 | #define L CR_CUR_LOCALS_PT(fid_parse_use_strict_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23003 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23004 | if (v7->cur_tok == TOK_STRING_LITERAL && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23005 | (strncmp(v7->tok, "\"use strict\"", v7->tok_len) == 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 23006 | strncmp(v7->tok, "'use strict'", v7->tok_len) == 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23007 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23008 | add_node(v7, a, AST_USE_STRICT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23009 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23010 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23011 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23012 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23013 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23015 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23016 | * static enum v7_err parse_body(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23017 | * enum v7_tok end) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23018 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23019 | fid_parse_body : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23020 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23021 | #define L CR_CUR_LOCALS_PT(fid_parse_body_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23022 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23023 | while (v7->cur_tok != L->arg.end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23024 | if (ACCEPT(TOK_FUNCTION)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23025 | if (v7->cur_tok != TOK_IDENTIFIER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23026 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23027 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23028 | L->start = add_node(v7, a, AST_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23029 | ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23030 | /* zero out var node pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23031 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23032 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23033 | add_inlined_node(v7, a, AST_FUNC_DECL, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23035 | CALL_PARSE_FUNCDECL(1, 0, fid_p_body_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23036 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23037 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23038 | CALL_PARSE_STATEMENT(fid_p_body_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23040 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23041 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23042 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23043 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23044 | /* static enum v7_err parse_statement(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23045 | fid_parse_statement : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23046 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23047 | #define L CR_CUR_LOCALS_PT(fid_parse_statement_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23048 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23049 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23050 | case TOK_SEMICOLON: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23051 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23052 | /* empty statement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23053 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23054 | case TOK_OPEN_CURLY: /* block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23055 | CALL_PARSE_BLOCK(fid_p_stat_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23056 | /* returning because no semicolon required */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23057 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23058 | case TOK_IF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23059 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23060 | CALL_PARSE_IF(fid_p_stat_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23061 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23062 | case TOK_WHILE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23063 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23064 | CALL_PARSE_WHILE(fid_p_stat_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23065 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23066 | case TOK_DO: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23067 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23068 | CALL_PARSE_DOWHILE(fid_p_stat_10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23069 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23070 | case TOK_FOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23071 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23072 | CALL_PARSE_FOR(fid_p_stat_11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23073 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23074 | case TOK_TRY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23075 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23076 | CALL_PARSE_TRY(fid_p_stat_12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23077 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23078 | case TOK_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23079 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23080 | CALL_PARSE_SWITCH(fid_p_stat_13); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23081 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23082 | case TOK_WITH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23083 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23084 | CALL_PARSE_WITH(fid_p_stat_14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23085 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23086 | case TOK_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23087 | if (!(v7->pstate.in_loop || v7->pstate.in_switch)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23088 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23089 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23090 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23091 | PARSE_WITH_OPT_ARG(AST_BREAK, AST_LABELED_BREAK, CALL_PARSE_IDENT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23092 | fid_p_stat_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23093 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23094 | case TOK_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23095 | if (!v7->pstate.in_loop) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23096 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23097 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23098 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23099 | PARSE_WITH_OPT_ARG(AST_CONTINUE, AST_LABELED_CONTINUE, CALL_PARSE_IDENT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23100 | fid_p_stat_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23101 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23102 | case TOK_RETURN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23103 | if (!v7->pstate.in_function) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23104 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23105 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23106 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23107 | PARSE_WITH_OPT_ARG(AST_RETURN, AST_VALUE_RETURN, CALL_PARSE_EXPRESSION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23108 | fid_p_stat_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23109 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23110 | case TOK_THROW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23111 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23112 | add_node(v7, a, AST_THROW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23113 | CALL_PARSE_EXPRESSION(fid_p_stat_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23114 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23115 | case TOK_DEBUGGER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23116 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23117 | add_node(v7, a, AST_DEBUGGER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23118 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23119 | case TOK_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23120 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23121 | CALL_PARSE_VAR(fid_p_stat_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23122 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23123 | case TOK_IDENTIFIER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23124 | if (lookahead(v7) == TOK_COLON) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23125 | add_inlined_node(v7, a, AST_LABEL, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23126 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23127 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23128 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23129 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23130 | /* fall through */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23131 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23132 | CALL_PARSE_EXPRESSION(fid_p_stat_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23133 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23134 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23135 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23136 | if (end_of_statement(v7) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23137 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23138 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23139 | ACCEPT(TOK_SEMICOLON); /* swallow optional semicolon */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23140 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23143 | /* static enum v7_err parse_expression(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23144 | fid_parse_expression : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23145 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23146 | #define L CR_CUR_LOCALS_PT(fid_parse_expression_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23147 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23148 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23149 | L->group = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23150 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23151 | CALL_PARSE_ASSIGN(fid_p_expr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23152 | if (ACCEPT(TOK_COMMA)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23153 | L->group = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23154 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23155 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23156 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23157 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23158 | if (L->group) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23159 | insert_node(v7, a, L->pos, AST_SEQ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23160 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23161 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23162 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23164 | /* static enum v7_err parse_assign(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23165 | fid_parse_assign : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23166 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23167 | #define L CR_CUR_LOCALS_PT(fid_parse_assign_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23168 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23169 | CALL_PARSE_BINARY(0, a->mbuf.len, fid_p_assign_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23170 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23171 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23173 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23174 | * static enum v7_err parse_binary(struct v7 *v7, struct ast *a, int level, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23175 | * ast_off_t pos) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23176 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23177 | #if 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 23178 | fid_parse_binary : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23179 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23180 | #define L CR_CUR_LOCALS_PT(fid_parse_binary_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23181 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23182 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23183 | * Note: we use macro CUR_POS instead of a local variable, since this |
Marko Mikulicic |
0:c0ecb8bf28eb | 23184 | * function is called really a lot, so, each byte on stack frame counts. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23185 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 23186 | * It will work a bit slower of course, but slowness is not a problem |
Marko Mikulicic |
0:c0ecb8bf28eb | 23187 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23188 | #define CUR_POS ((L->level > L->arg.min_level) ? L->saved_mbuf_len : L->arg.pos) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23189 | L->saved_mbuf_len = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23191 | CALL_PARSE_PREFIX(fid_p_binary_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23192 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23193 | for (L->level = (int) ARRAY_SIZE(levels) - 1; L->level >= L->arg.min_level; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23194 | L->level--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23195 | for (L->i = 0; L->i < levels[L->level].len; L->i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23196 | L->tok = levels[L->level].parts[L->i].start_tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23197 | L->ast = levels[L->level].parts[L->i].start_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23198 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23199 | if (v7->pstate.inhibit_in && L->tok == TOK_IN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23200 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23203 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23204 | * Ternary operator sits in the middle of the binary operator |
Marko Mikulicic |
0:c0ecb8bf28eb | 23205 | * precedence chain. Deal with it as an exception and don't break |
Marko Mikulicic |
0:c0ecb8bf28eb | 23206 | * the chain. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23207 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23208 | if (L->tok == TOK_QUESTION && v7->cur_tok == TOK_QUESTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23209 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23210 | CALL_PARSE_ASSIGN(fid_p_binary_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23211 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23212 | CALL_PARSE_ASSIGN(fid_p_binary_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23213 | insert_node(v7, a, CUR_POS, AST_COND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23214 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23215 | } else if (ACCEPT(L->tok)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23216 | if (levels[L->level].left_to_right) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23217 | insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23218 | CALL_PARSE_BINARY(L->level, CUR_POS, fid_p_binary_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23219 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23220 | CALL_PARSE_BINARY(L->level, a->mbuf.len, fid_p_binary_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23221 | insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23222 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23223 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23224 | } while (L->ast = (enum ast_tag)(L->ast + 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 23225 | L->tok < levels[L->level].parts[L->i].end_tok && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23226 | (L->tok = (enum v7_tok)(L->tok + 1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23227 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23228 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23229 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23230 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23231 | #undef CUR_POS |
Marko Mikulicic |
0:c0ecb8bf28eb | 23232 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23233 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23234 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23235 | /* enum v7_err parse_prefix(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23236 | fid_parse_prefix : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23237 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23238 | #define L CR_CUR_LOCALS_PT(fid_parse_prefix_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23239 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23240 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23241 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23242 | case TOK_PLUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23243 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23244 | add_node(v7, a, AST_POSITIVE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23245 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23246 | case TOK_MINUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23247 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23248 | add_node(v7, a, AST_NEGATIVE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23249 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23250 | case TOK_PLUS_PLUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23251 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23252 | add_node(v7, a, AST_PREINC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23253 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23254 | case TOK_MINUS_MINUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23255 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23256 | add_node(v7, a, AST_PREDEC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23257 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23258 | case TOK_TILDA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23259 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23260 | add_node(v7, a, AST_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23261 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23262 | case TOK_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23263 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23264 | add_node(v7, a, AST_LOGICAL_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23265 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23266 | case TOK_VOID: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23267 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23268 | add_node(v7, a, AST_VOID); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23269 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23270 | case TOK_DELETE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23271 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23272 | add_node(v7, a, AST_DELETE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23273 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23274 | case TOK_TYPEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23275 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23276 | add_node(v7, a, AST_TYPEOF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23277 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23278 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23279 | CALL_PARSE_POSTFIX(fid_p_prefix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23280 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23281 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23282 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23283 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23285 | /* static enum v7_err parse_postfix(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23286 | fid_parse_postfix : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23287 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23288 | #define L CR_CUR_LOCALS_PT(fid_parse_postfix_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23289 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23290 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23291 | CALL_PARSE_CALLEXPR(fid_p_postfix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23293 | if (v7->after_newline) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23294 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23296 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23297 | case TOK_PLUS_PLUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23298 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23299 | insert_node(v7, a, L->pos, AST_POSTINC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23300 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23301 | case TOK_MINUS_MINUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23302 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23303 | insert_node(v7, a, L->pos, AST_POSTDEC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23304 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23305 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23306 | break; /* nothing */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23307 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23308 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23309 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23311 | /* static enum v7_err parse_callexpr(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23312 | fid_parse_callexpr : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23313 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23314 | #define L CR_CUR_LOCALS_PT(fid_parse_callexpr_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23315 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23316 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23317 | CALL_PARSE_NEWEXPR(fid_p_callexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23319 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23320 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23321 | case TOK_DOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23322 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23323 | CALL_PARSE_MEMBER(L->pos, fid_p_callexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23324 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23325 | case TOK_OPEN_PAREN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23326 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23327 | CALL_PARSE_ARGLIST(fid_p_callexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23328 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23329 | insert_node(v7, a, L->pos, AST_CALL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23330 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23331 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23332 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23333 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23335 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23337 | /* static enum v7_err parse_newexpr(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23338 | fid_parse_newexpr : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23339 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23340 | #define L CR_CUR_LOCALS_PT(fid_parse_newexpr_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23341 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23342 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23343 | case TOK_NEW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23344 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23345 | L->start = add_node(v7, a, AST_NEW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23346 | CALL_PARSE_MEMBEREXPR(fid_p_newexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23347 | if (ACCEPT(TOK_OPEN_PAREN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23348 | CALL_PARSE_ARGLIST(fid_p_newexpr_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23349 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23350 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23351 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23352 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23353 | case TOK_FUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23354 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23355 | CALL_PARSE_FUNCDECL(0, 0, fid_p_newexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23356 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23357 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23358 | CALL_PARSE_TERMINAL(fid_p_newexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23359 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23361 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23362 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23364 | /* static enum v7_err parse_terminal(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23365 | fid_parse_terminal : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23366 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23367 | #define L CR_CUR_LOCALS_PT(fid_parse_terminal_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23368 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23369 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23370 | case TOK_OPEN_PAREN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23371 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23372 | CALL_PARSE_EXPRESSION(fid_p_terminal_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23373 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23374 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23375 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23376 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23377 | L->start = add_node(v7, a, AST_ARRAY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23378 | while (v7->cur_tok != TOK_CLOSE_BRACKET) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23379 | if (v7->cur_tok == TOK_COMMA) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23380 | /* Array literals allow missing elements, e.g. [,,1,] */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23381 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23382 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23383 | CALL_PARSE_ASSIGN(fid_p_terminal_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23384 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23385 | ACCEPT(TOK_COMMA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23386 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23387 | EXPECT(TOK_CLOSE_BRACKET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23388 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23389 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23390 | case TOK_OPEN_CURLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23391 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23392 | L->start = add_node(v7, a, AST_OBJECT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23393 | if (v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23394 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23395 | if (v7->cur_tok == TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23396 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23397 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23398 | CALL_PARSE_PROP(fid_p_terminal_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23399 | } while (ACCEPT(TOK_COMMA)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23400 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23401 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23402 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23403 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23404 | case TOK_THIS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23405 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23406 | add_node(v7, a, AST_THIS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23407 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23408 | case TOK_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23409 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23410 | add_node(v7, a, AST_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23411 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23412 | case TOK_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23413 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23414 | add_node(v7, a, AST_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23415 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23416 | case TOK_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23417 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23418 | add_node(v7, a, AST_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23419 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23420 | case TOK_STRING_LITERAL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23421 | add_inlined_node(v7, a, AST_STRING, v7->tok + 1, v7->tok_len - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23422 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23423 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23424 | case TOK_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23425 | add_inlined_node(v7, a, AST_NUM, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23426 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23427 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23428 | case TOK_REGEX_LITERAL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23429 | add_inlined_node(v7, a, AST_REGEX, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23430 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23431 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23432 | case TOK_IDENTIFIER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23433 | if (v7->tok_len == 9 && strncmp(v7->tok, "undefined", v7->tok_len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23434 | add_node(v7, a, AST_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23435 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23436 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23437 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23438 | /* fall through */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23439 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23440 | CALL_PARSE_IDENT(fid_p_terminal_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23442 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23445 | /* static enum v7_err parse_block(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23446 | fid_parse_block : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23447 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23448 | #define L CR_CUR_LOCALS_PT(fid_parse_block_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23449 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23450 | EXPECT(TOK_OPEN_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23451 | CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_block_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23452 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23453 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23454 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23456 | /* static enum v7_err parse_if(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23457 | fid_parse_if : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23458 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23459 | #define L CR_CUR_LOCALS_PT(fid_parse_if_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23460 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23461 | L->start = add_node(v7, a, AST_IF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23462 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23463 | CALL_PARSE_EXPRESSION(fid_p_if_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23464 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23465 | CALL_PARSE_STATEMENT(fid_p_if_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23466 | ast_set_skip(a, L->start, AST_END_IF_TRUE_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23467 | if (ACCEPT(TOK_ELSE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23468 | CALL_PARSE_STATEMENT(fid_p_if_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23469 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23470 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23471 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23472 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23474 | /* static enum v7_err parse_while(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23475 | fid_parse_while : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23476 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23477 | #define L CR_CUR_LOCALS_PT(fid_parse_while_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23478 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23479 | L->start = add_node(v7, a, AST_WHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23480 | L->saved_in_loop = v7->pstate.in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23481 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23482 | CALL_PARSE_EXPRESSION(fid_p_while_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23483 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23484 | v7->pstate.in_loop = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23485 | CALL_PARSE_STATEMENT(fid_p_while_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23486 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23487 | v7->pstate.in_loop = L->saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23488 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23489 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23491 | /* static enum v7_err parse_ident(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23492 | fid_parse_ident : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23493 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23494 | #define L CR_CUR_LOCALS_PT(fid_parse_ident_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23495 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23496 | if (v7->cur_tok == TOK_IDENTIFIER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23497 | add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23498 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23499 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23500 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23501 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23502 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23503 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23504 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23505 | * static enum v7_err parse_ident_allow_reserved_words(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23506 | * struct ast *a) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23507 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 23508 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23509 | fid_parse_ident_allow_reserved_words : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23510 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23511 | #define L CR_CUR_LOCALS_PT(fid_parse_ident_allow_reserved_words_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23512 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23513 | /* Allow reserved words as property names. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23514 | if (is_reserved_word_token(v7->cur_tok)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23515 | add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23516 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23517 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23518 | CALL_PARSE_IDENT(fid_p_ident_arw_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23519 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23520 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23521 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23523 | /* static enum v7_err parse_funcdecl(struct v7 *, struct ast *, int, int) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23524 | fid_parse_funcdecl : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23525 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23526 | #define L CR_CUR_LOCALS_PT(fid_parse_funcdecl_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23527 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23528 | L->start = add_node(v7, a, AST_FUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23529 | L->outer_last_var_node = v7->last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23530 | L->saved_in_function = v7->pstate.in_function; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23531 | L->saved_in_strict = v7->pstate.in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23533 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23534 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23536 | CR_TRY(fid_p_funcdecl_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23537 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23538 | if (L->arg.reserved_name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23539 | CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(fid_p_funcdecl_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23540 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23541 | CALL_PARSE_IDENT(fid_p_funcdecl_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23544 | CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_2, fid_p_funcdecl_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23545 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23546 | if (L->arg.require_named) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23547 | /* function name is required, so, rethrow SYNTAX ERROR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23548 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23549 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23550 | /* it's ok not to have a function name, just insert NOP */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23551 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23552 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23553 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23554 | CR_ENDCATCH(fid_p_funcdecl_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23556 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23557 | CALL_PARSE_ARGLIST(fid_p_funcdecl_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23558 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23559 | ast_set_skip(a, L->start, AST_FUNC_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23560 | v7->pstate.in_function = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23561 | EXPECT(TOK_OPEN_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23563 | CR_TRY(fid_p_funcdecl_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23564 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23565 | CALL_PARSE_USE_STRICT(fid_p_funcdecl_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23566 | v7->pstate.in_strict = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23567 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23568 | CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_5, fid_p_funcdecl_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23569 | CR_ENDCATCH(fid_p_funcdecl_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23571 | CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_funcdecl_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23572 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23573 | v7->pstate.in_strict = L->saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23574 | v7->pstate.in_function = L->saved_in_function; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23575 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23576 | v7->last_var_node = L->outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23578 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23579 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23581 | /* static enum v7_err parse_arglist(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23582 | fid_parse_arglist : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23583 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23584 | #define L CR_CUR_LOCALS_PT(fid_parse_arglist_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23585 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23586 | if (v7->cur_tok != TOK_CLOSE_PAREN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23587 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23588 | CALL_PARSE_ASSIGN(fid_p_arglist_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23589 | } while (ACCEPT(TOK_COMMA)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23590 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23591 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23592 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23594 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23595 | * static enum v7_err parse_member(struct v7 *v7, struct ast *a, ast_off_t pos) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23596 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23597 | fid_parse_member : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23598 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23599 | #define L CR_CUR_LOCALS_PT(fid_parse_member_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23600 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23601 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23602 | case TOK_DOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23603 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23604 | /* Allow reserved words as member identifiers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23605 | if (is_reserved_word_token(v7->cur_tok) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 23606 | v7->cur_tok == TOK_IDENTIFIER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23607 | insert_inlined_node(v7, a, L->arg.pos, AST_MEMBER, v7->tok, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23608 | v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23609 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23610 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23611 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23612 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23613 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23614 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23615 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23616 | CALL_PARSE_EXPRESSION(fid_p_member_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23617 | EXPECT(TOK_CLOSE_BRACKET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23618 | insert_node(v7, a, L->arg.pos, AST_INDEX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23619 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23620 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23621 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23623 | /* not necessary, but let it be anyway */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23624 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23625 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23627 | /* static enum v7_err parse_memberexpr(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23628 | fid_parse_memberexpr : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23629 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23630 | #define L CR_CUR_LOCALS_PT(fid_parse_memberexpr_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23631 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23632 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23633 | CALL_PARSE_NEWEXPR(fid_p_memberexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23634 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23635 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23636 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23637 | case TOK_DOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23638 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23639 | CALL_PARSE_MEMBER(L->pos, fid_p_memberexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23640 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23641 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23642 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23643 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23644 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23645 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23646 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23647 | /* static enum v7_err parse_var(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23648 | fid_parse_var : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23649 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23650 | #define L CR_CUR_LOCALS_PT(fid_parse_var_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23651 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23652 | L->start = add_node(v7, a, AST_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23653 | ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23654 | /* zero out var node pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23655 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23656 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23657 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23658 | add_inlined_node(v7, a, AST_VAR_DECL, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23659 | EXPECT(TOK_IDENTIFIER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23660 | if (ACCEPT(TOK_ASSIGN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23661 | CALL_PARSE_ASSIGN(fid_p_var_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23662 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23663 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23664 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23665 | } while (ACCEPT(TOK_COMMA)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23666 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23667 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23668 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23670 | /* static enum v7_err parse_prop(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23671 | fid_parse_prop : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23672 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23673 | #define L CR_CUR_LOCALS_PT(fid_parse_prop_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23674 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23675 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 23676 | if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23677 | strncmp(v7->tok, "get", v7->tok_len) == 0 && lookahead(v7) != TOK_COLON) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23678 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23679 | add_node(v7, a, AST_GETTER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23680 | CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_1_getter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23681 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 23682 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23683 | if (v7->cur_tok == TOK_IDENTIFIER && lookahead(v7) == TOK_OPEN_PAREN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23684 | /* ecmascript 6 feature */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23685 | CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23686 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 23687 | } else if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23688 | strncmp(v7->tok, "set", v7->tok_len) == 0 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23689 | lookahead(v7) != TOK_COLON) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23690 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23691 | add_node(v7, a, AST_SETTER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23692 | CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_3_setter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23693 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23694 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23695 | /* Allow reserved words as property names. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23696 | if (is_reserved_word_token(v7->cur_tok) || v7->cur_tok == TOK_IDENTIFIER || |
Marko Mikulicic |
0:c0ecb8bf28eb | 23697 | v7->cur_tok == TOK_NUMBER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23698 | add_inlined_node(v7, a, AST_PROP, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23699 | } else if (v7->cur_tok == TOK_STRING_LITERAL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23700 | add_inlined_node(v7, a, AST_PROP, v7->tok + 1, v7->tok_len - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23701 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23702 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23703 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23704 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23705 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23706 | CALL_PARSE_ASSIGN(fid_p_prop_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23707 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23708 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23709 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23711 | /* static enum v7_err parse_dowhile(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23712 | fid_parse_dowhile : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23713 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23714 | #define L CR_CUR_LOCALS_PT(fid_parse_dowhile_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23715 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23716 | L->start = add_node(v7, a, AST_DOWHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23717 | L->saved_in_loop = v7->pstate.in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23719 | v7->pstate.in_loop = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23720 | CALL_PARSE_STATEMENT(fid_p_dowhile_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23721 | v7->pstate.in_loop = L->saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23722 | ast_set_skip(a, L->start, AST_DO_WHILE_COND_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23723 | EXPECT(TOK_WHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23724 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23725 | CALL_PARSE_EXPRESSION(fid_p_dowhile_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23726 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23727 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23728 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23729 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23730 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23731 | /* static enum v7_err parse_for(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23732 | fid_parse_for : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23733 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23734 | #define L CR_CUR_LOCALS_PT(fid_parse_for_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23735 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23736 | /* TODO(mkm): for of, for each in */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23737 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23738 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23739 | int saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23740 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23741 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23742 | L->start = add_node(v7, a, AST_FOR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23743 | L->saved_in_loop = v7->pstate.in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23745 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23746 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23747 | if (parse_optional(v7, a, TOK_SEMICOLON)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23748 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23749 | * TODO(mkm): make this reentrant otherwise this pearl won't parse: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23750 | * for((function(){return 1 in o.a ? o : x})().a in [1,2,3]) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23751 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23752 | v7->pstate.inhibit_in = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23753 | if (ACCEPT(TOK_VAR)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23754 | CALL_PARSE_VAR(fid_p_for_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23755 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23756 | CALL_PARSE_EXPRESSION(fid_p_for_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23757 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23758 | v7->pstate.inhibit_in = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23760 | if (ACCEPT(TOK_IN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23761 | CALL_PARSE_EXPRESSION(fid_p_for_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23762 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23763 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23764 | * Assumes that for and for in have the same AST format which is |
Marko Mikulicic |
0:c0ecb8bf28eb | 23765 | * suboptimal but avoids the need of fixing up the var offset chain. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23766 | * TODO(mkm) improve this |
Marko Mikulicic |
0:c0ecb8bf28eb | 23767 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23768 | ast_modify_tag(a, L->start - 1, AST_FOR_IN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23769 | goto for_loop_body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23770 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23771 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23773 | EXPECT(TOK_SEMICOLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23774 | if (parse_optional(v7, a, TOK_SEMICOLON)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23775 | CALL_PARSE_EXPRESSION(fid_p_for_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23776 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23777 | EXPECT(TOK_SEMICOLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23778 | if (parse_optional(v7, a, TOK_CLOSE_PAREN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23779 | CALL_PARSE_EXPRESSION(fid_p_for_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23780 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23781 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23782 | for_loop_body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23783 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23784 | ast_set_skip(a, L->start, AST_FOR_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23785 | v7->pstate.in_loop = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23786 | CALL_PARSE_STATEMENT(fid_p_for_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23787 | v7->pstate.in_loop = L->saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23788 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23789 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23790 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23792 | /* static enum v7_err parse_try(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23793 | fid_parse_try : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23794 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23795 | #define L CR_CUR_LOCALS_PT(fid_parse_try_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23796 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23797 | L->start = add_node(v7, a, AST_TRY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23798 | L->catch_or_finally = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23799 | CALL_PARSE_BLOCK(fid_p_try_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23800 | ast_set_skip(a, L->start, AST_TRY_CATCH_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23801 | if (ACCEPT(TOK_CATCH)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23802 | L->catch_or_finally = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23803 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23804 | CALL_PARSE_IDENT(fid_p_try_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23805 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23806 | CALL_PARSE_BLOCK(fid_p_try_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23807 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23808 | ast_set_skip(a, L->start, AST_TRY_FINALLY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23809 | if (ACCEPT(TOK_FINALLY)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23810 | L->catch_or_finally = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23811 | CALL_PARSE_BLOCK(fid_p_try_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23812 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23813 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23815 | /* make sure `catch` and `finally` aren't both missing */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23816 | if (!L->catch_or_finally) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23817 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23818 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23820 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23823 | /* static enum v7_err parse_switch(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23824 | fid_parse_switch : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23825 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23826 | #define L CR_CUR_LOCALS_PT(fid_parse_switch_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23827 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23828 | L->start = add_node(v7, a, AST_SWITCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23829 | L->saved_in_switch = v7->pstate.in_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23831 | ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP); /* clear out */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23832 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23833 | CALL_PARSE_EXPRESSION(fid_p_switch_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23834 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23835 | EXPECT(TOK_OPEN_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23836 | v7->pstate.in_switch = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23837 | while (v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23838 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23839 | case TOK_CASE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23840 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23841 | L->case_start = add_node(v7, a, AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23842 | CALL_PARSE_EXPRESSION(fid_p_switch_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23843 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23844 | while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23845 | v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23846 | CALL_PARSE_STATEMENT(fid_p_switch_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23848 | ast_set_skip(a, L->case_start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23849 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23850 | case TOK_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23851 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23852 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23853 | ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23854 | L->case_start = add_node(v7, a, AST_DEFAULT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23855 | while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23856 | v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23857 | CALL_PARSE_STATEMENT(fid_p_switch_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23859 | ast_set_skip(a, L->case_start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23860 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23861 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23862 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23864 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23865 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23866 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23867 | v7->pstate.in_switch = L->saved_in_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23868 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23869 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23871 | /* static enum v7_err parse_with(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23872 | fid_parse_with : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23873 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23874 | #define L CR_CUR_LOCALS_PT(fid_parse_with_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23875 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23876 | L->start = add_node(v7, a, AST_WITH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23877 | if (v7->pstate.in_strict) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23878 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23879 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23880 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23881 | CALL_PARSE_EXPRESSION(fid_p_with_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23882 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23883 | CALL_PARSE_STATEMENT(fid_p_with_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23884 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23885 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23888 | fid_none: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23889 | /* stack is empty, so we're done; return */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23890 | return rc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23893 | V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23894 | size_t src_len, int is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23895 | enum v7_err rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23896 | const char *error_msg = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23897 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23898 | struct cr_ctx cr_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23899 | union user_arg_ret arg_retval; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23900 | enum cr_status rc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23901 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23902 | struct stack_track_ctx stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23903 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23904 | int saved_line_no = v7->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23906 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23907 | v7_stack_track_start(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23908 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23910 | v7->pstate.source_code = v7->pstate.pc = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23911 | v7->pstate.src_end = src + src_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23912 | v7->pstate.file_name = "<stdin>"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23913 | v7->pstate.line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23914 | v7->pstate.in_function = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23915 | v7->pstate.in_loop = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23916 | v7->pstate.in_switch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23918 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23919 | * TODO(dfrank): `v7->parser.line_no` vs `v7->line_no` is confusing. probaby |
Marko Mikulicic |
0:c0ecb8bf28eb | 23920 | * we need to refactor it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23921 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 23922 | * See comment for v7->line_no in core.h for some details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23923 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23924 | v7->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23926 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23927 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23928 | * setup initial state for "after newline" tracking. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23929 | * next_tok will consume our token and position the current line |
Marko Mikulicic |
0:c0ecb8bf28eb | 23930 | * position at the beginning of the next token. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23931 | * While processing the first token, both the leading and the |
Marko Mikulicic |
0:c0ecb8bf28eb | 23932 | * trailing newlines will be counted and thus it will create a spurious |
Marko Mikulicic |
0:c0ecb8bf28eb | 23933 | * "after newline" condition at the end of the first token |
Marko Mikulicic |
0:c0ecb8bf28eb | 23934 | * regardless if there is actually a newline after it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23935 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23936 | for (p = src; isspace((int) *p); p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23937 | if (*p == '\n') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23938 | v7->pstate.prev_line_no++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23939 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23940 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23942 | /* init cr context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23943 | cr_context_init(&cr_ctx, &arg_retval, sizeof(arg_retval), _fid_descrs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23945 | /* prepare first function call: fid_mul_sum */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23946 | if (is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23947 | CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_terminal); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23948 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23949 | CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_script); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23950 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23952 | /* proceed to coroutine execution */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23953 | rc = parser_cr_exec(&cr_ctx, v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23955 | /* set `rcode` depending on coroutine state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23956 | switch (rc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23957 | case CR_RES__OK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23958 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23959 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23960 | case CR_RES__ERR_UNCAUGHT_EXCEPTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23961 | switch ((enum parser_exc_id) CR_THROWN_C(&cr_ctx)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23962 | case PARSER_EXC_ID__SYNTAX_ERROR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23963 | rcode = V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23964 | error_msg = "Syntax error"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23965 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23967 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23968 | rcode = V7_INTERNAL_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23969 | error_msg = "Internal error: no exception id set"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23970 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23971 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23972 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23973 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23974 | rcode = V7_INTERNAL_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23975 | error_msg = "Internal error: unexpected parser coroutine return code"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23976 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23977 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23979 | #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23980 | /* remember how much stack space was consumed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23982 | if (v7->parser_stack_data_max_size < cr_ctx.stack_data.size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23983 | v7->parser_stack_data_max_size = cr_ctx.stack_data.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23984 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 23985 | printf("parser_stack_data_max_size=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 23986 | (unsigned int) v7->parser_stack_data_max_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23987 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23988 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23989 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23990 | if (v7->parser_stack_ret_max_size < cr_ctx.stack_ret.size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23991 | v7->parser_stack_ret_max_size = cr_ctx.stack_ret.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23992 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 23993 | printf("parser_stack_ret_max_size=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 23994 | (unsigned int) v7->parser_stack_ret_max_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23995 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23996 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23998 | #if defined(CR_TRACK_MAX_STACK_LEN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23999 | if (v7->parser_stack_data_max_len < cr_ctx.stack_data_max_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24000 | v7->parser_stack_data_max_len = cr_ctx.stack_data_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24001 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 24002 | printf("parser_stack_data_max_len=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24003 | (unsigned int) v7->parser_stack_data_max_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24004 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24005 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24007 | if (v7->parser_stack_ret_max_len < cr_ctx.stack_ret_max_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24008 | v7->parser_stack_ret_max_len = cr_ctx.stack_ret_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24009 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 24010 | printf("parser_stack_ret_max_len=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24011 | (unsigned int) v7->parser_stack_ret_max_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24012 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24013 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24014 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24015 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24016 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24018 | /* free resources occupied by context (at least, "stack" arrays) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24019 | cr_context_free(&cr_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24021 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24022 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24023 | int diff = v7_stack_track_end(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24024 | if (diff > v7->stack_stat[V7_STACK_STAT_PARSER]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24025 | v7->stack_stat[V7_STACK_STAT_PARSER] = diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24027 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24028 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24029 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24030 | /* Check if AST was overflown */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24031 | if (a->has_overflow) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24032 | rcode = v7_throwf(v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24033 | "Script too large (try V7_LARGE_AST build option)"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24034 | V7_THROW(V7_AST_TOO_LARGE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24035 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24037 | if (rcode == V7_OK && v7->cur_tok != TOK_END_OF_INPUT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24038 | rcode = V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24039 | error_msg = "Syntax error"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24040 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24042 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24043 | unsigned long col = get_column(v7->pstate.source_code, v7->tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24044 | int line_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24046 | assert(error_msg != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24047 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24048 | for (p = v7->tok - col; p < v7->pstate.src_end && *p != '\0' && *p != '\n'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24049 | p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24050 | line_len++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24051 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24053 | /* fixup line number: line_no points to the beginning of the next token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24054 | for (; p < v7->pstate.pc; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24055 | if (*p == '\n') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24056 | v7->pstate.line_no--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24057 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24060 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24061 | * We already have a proper `rcode`, that's why we discard returned value |
Marko Mikulicic |
0:c0ecb8bf28eb | 24062 | * of `v7_throwf()`, which is always `V7_EXEC_EXCEPTION`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24063 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24064 | * TODO(dfrank): probably get rid of distinct error types, and use just |
Marko Mikulicic |
0:c0ecb8bf28eb | 24065 | * `V7_JS_EXCEPTION`. However it would be good to have a way to get exact |
Marko Mikulicic |
0:c0ecb8bf28eb | 24066 | * error type, so probably error object should contain some property with |
Marko Mikulicic |
0:c0ecb8bf28eb | 24067 | * error code, but it would make exceptions even more expensive, etc, etc. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24068 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24069 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24070 | enum v7_err _tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24071 | _tmp = v7_throwf(v7, SYNTAX_ERROR, "%s at line %d col %lu:\n%.*s\n%*s^", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24072 | error_msg, v7->pstate.line_no, col, line_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24073 | v7->tok - col, (int) col - 1, ""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24074 | (void) _tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24075 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24076 | V7_THROW(rcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24079 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24080 | v7->line_no = saved_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24081 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24082 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24084 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24085 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 24086 | #line 1 "v7/src/compiler.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24087 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24088 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24089 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 24090 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 24091 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24092 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24093 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24094 | /* Amalgamated: #include "v7/src/compiler.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24095 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24096 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24097 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24098 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24099 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24100 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24102 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24104 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24105 | * The bytecode compiler takes an AST as input and produces one or more |
Marko Mikulicic |
0:c0ecb8bf28eb | 24106 | * bcode structure as output. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24107 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24108 | * Each script or function body is compiled into it's own bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24109 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24110 | * Each bcode stream produces a new value on the stack, i.e. its overall |
Marko Mikulicic |
0:c0ecb8bf28eb | 24111 | * stack diagram is: `( -- a)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24112 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24113 | * This value will be then popped by the function caller or by v7_exec in case |
Marko Mikulicic |
0:c0ecb8bf28eb | 24114 | * of scripts. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24115 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24116 | * In JS, the value of a script is the value of the last statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24117 | * A script with no statement has an `undefined` value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24118 | * Functions instead require an explicit return value, so this matters only |
Marko Mikulicic |
0:c0ecb8bf28eb | 24119 | * for `v7_exec` and JS `eval`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24120 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24121 | * Since an empty script has an undefined value, and each script has to |
Marko Mikulicic |
0:c0ecb8bf28eb | 24122 | * yield a value, the script/function prologue consists of a PUSH_UNDEFINED. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24123 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24124 | * Each statement will be compiled to push a value on the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24125 | * When a statement begins evaluating, the current TOS is thus either |
Marko Mikulicic |
0:c0ecb8bf28eb | 24126 | * the value of the previous statement or `undefined` in case of the first |
Marko Mikulicic |
0:c0ecb8bf28eb | 24127 | * statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24128 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24129 | * Every statement of a given script/function body always evaluates at the same |
Marko Mikulicic |
0:c0ecb8bf28eb | 24130 | * stack depth. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24131 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24132 | * In order to achieve that, after a statement is compiled out, a SWAP_DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24133 | * opcode is emitted, that drops the value of the previous statement (or the |
Marko Mikulicic |
0:c0ecb8bf28eb | 24134 | * initial `undefined`). Dropping the value after the next statement is |
Marko Mikulicic |
0:c0ecb8bf28eb | 24135 | * evaluated and not before has allows us to correctly implement exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 24136 | * behaviour and the break statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24137 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24138 | * Compound statements are constructs such as `if`/`while`/`for`/`try`. These |
Marko Mikulicic |
0:c0ecb8bf28eb | 24139 | * constructs contain a body consisting of a possibly empty statement list. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24140 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24141 | * Unlike normal statements, compound statements don't produce a value |
Marko Mikulicic |
0:c0ecb8bf28eb | 24142 | * themselves. Their value is either the value of their last executed statement |
Marko Mikulicic |
0:c0ecb8bf28eb | 24143 | * in their body, or the previous statement in case their body is empty or not |
Marko Mikulicic |
0:c0ecb8bf28eb | 24144 | * evaluated at all. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24145 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24146 | * An example is: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24147 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24148 | * [source,js] |
Marko Mikulicic |
0:c0ecb8bf28eb | 24149 | * ---- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24150 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24151 | * 42; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24152 | * someUnexistingVariable; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24153 | * } catch(e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24154 | * while(true) {} |
Marko Mikulicic |
0:c0ecb8bf28eb | 24155 | * if(true) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24156 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24157 | * if(false) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24158 | * 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24159 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24160 | * break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24161 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24162 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24163 | * ---- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24164 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24166 | static const enum ast_tag assign_ast_map[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24167 | AST_REM, AST_MUL, AST_DIV, AST_XOR, AST_ADD, AST_SUB, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24168 | AST_OR, AST_AND, AST_LSHIFT, AST_RSHIFT, AST_URSHIFT}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24170 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24171 | extern void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24172 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24173 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24174 | V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24175 | struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24177 | V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24178 | ast_off_t *ppos, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24180 | V7_PRIVATE enum v7_err binary_op(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24181 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24182 | uint8_t op; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24183 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24184 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24186 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24187 | case AST_ADD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24188 | op = OP_ADD; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24189 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24190 | case AST_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24191 | op = OP_SUB; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24192 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24193 | case AST_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24194 | op = OP_REM; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24195 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24196 | case AST_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24197 | op = OP_MUL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24198 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24199 | case AST_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24200 | op = OP_DIV; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24201 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24202 | case AST_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24203 | op = OP_LSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24204 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24205 | case AST_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24206 | op = OP_RSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24207 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24208 | case AST_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24209 | op = OP_URSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24210 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24211 | case AST_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24212 | op = OP_OR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24213 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24214 | case AST_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24215 | op = OP_XOR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24216 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24217 | case AST_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24218 | op = OP_AND; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24219 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24220 | case AST_EQ_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24221 | op = OP_EQ_EQ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24222 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24223 | case AST_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24224 | op = OP_EQ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24225 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24226 | case AST_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24227 | op = OP_NE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24228 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24229 | case AST_NE_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24230 | op = OP_NE_NE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24231 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24232 | case AST_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24233 | op = OP_LT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24234 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24235 | case AST_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24236 | op = OP_LE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24237 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24238 | case AST_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24239 | op = OP_GT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24240 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24241 | case AST_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24242 | op = OP_GE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24243 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24244 | case AST_INSTANCEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24245 | op = OP_INSTANCEOF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24246 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24247 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24248 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown binary ast node"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24249 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24251 | bcode_op(bbuilder, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24252 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24253 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24254 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24256 | V7_PRIVATE enum v7_err compile_binary(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24257 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24258 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24259 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24260 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24261 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24262 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24263 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24264 | V7_TRY(binary_op(bbuilder, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24265 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24266 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24267 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24268 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24269 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24270 | * `pos` should be an offset of the byte right after a tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 24271 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24272 | static lit_t string_lit(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24273 | ast_off_t pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24274 | size_t i = 0, name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24275 | val_t v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24276 | struct mbuf *m = &bbuilder->lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24277 | char *name = ast_get_inlined_data(a, pos, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24278 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24279 | /* temp disabled because of short lits */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24280 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 24281 | for (i = 0; i < m->len / sizeof(val_t); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24282 | v = ((val_t *) m->buf)[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24283 | if (v7_is_string(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24284 | size_t l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24285 | const char *s = v7_get_string(bbuilder->v7, &v, &l); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24286 | if (name_len == l && memcmp(name, s, name_len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24287 | lit_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24288 | memset(&res, 0, sizeof(res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24289 | res.idx = i + bcode_max_inline_type_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24290 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24291 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24292 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24293 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24294 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 24295 | (void) i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24296 | (void) v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24297 | (void) m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24298 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24299 | return bcode_add_lit(bbuilder, v7_mk_string(bbuilder->v7, name, name_len, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24302 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 24303 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 24304 | static enum v7_err regexp_lit(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24305 | ast_off_t pos, lit_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24306 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24307 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24308 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24309 | char *name = ast_get_inlined_data(a, pos, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24310 | val_t tmp = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24311 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24312 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24313 | for (p = name + name_len - 1; *p != '/';) p--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24315 | V7_TRY(v7_mk_regexp(bbuilder->v7, name + 1, p - (name + 1), p + 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24316 | (name + name_len) - p - 1, &tmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24318 | *res = bcode_add_lit(bbuilder, tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24320 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24321 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24323 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24324 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24325 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 24326 | static void append_lineno_if_changed(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24327 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24328 | int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24329 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24330 | if (line_no != 0 && line_no != v7->line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24331 | v7->line_no = line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24332 | bcode_append_lineno(bbuilder, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24333 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24335 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 24336 | static void append_lineno_if_changed(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24337 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24338 | int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24339 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24340 | (void) bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24341 | (void) line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24343 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24345 | static enum ast_tag fetch_tag(struct v7 *v7, struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24346 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24347 | ast_off_t *ppos_after_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24348 | enum ast_tag ret = ast_fetch_tag(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24349 | int line_no = ast_get_line_no(a, *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24350 | append_lineno_if_changed(v7, bbuilder, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24351 | if (ppos_after_tag != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24352 | *ppos_after_tag = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24354 | ast_move_to_children(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24355 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24356 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24358 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24359 | * a++ and a-- need to ignore the updated value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24360 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24361 | * Call this before updating the lhs. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24362 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24363 | static void fixup_post_op(struct bcode_builder *bbuilder, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24364 | if (tag == AST_POSTINC || tag == AST_POSTDEC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24365 | bcode_op(bbuilder, OP_UNSTASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24366 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24367 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24369 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24370 | * evaluate rhs expression. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24371 | * ++a and a++ are equivalent to a+=1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 24372 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24373 | static enum v7_err eval_assign_rhs(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24374 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24375 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24376 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24377 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24379 | /* a++ and a-- need to preserve initial value. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24380 | if (tag == AST_POSTINC || tag == AST_POSTDEC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24381 | bcode_op(bbuilder, OP_STASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24382 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24383 | if (tag >= AST_PREINC && tag <= AST_POSTDEC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24384 | bcode_op(bbuilder, OP_PUSH_ONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24385 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24386 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24387 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24389 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24390 | case AST_PREINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24391 | case AST_POSTINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24392 | bcode_op(bbuilder, OP_ADD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24393 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24394 | case AST_PREDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24395 | case AST_POSTDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24396 | bcode_op(bbuilder, OP_SUB); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24397 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24398 | case AST_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24399 | /* no operation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24400 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24401 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24402 | binary_op(bbuilder, assign_ast_map[tag - AST_ASSIGN - 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24403 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24405 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24406 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24409 | static enum v7_err compile_assign(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24410 | ast_off_t *ppos, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24411 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24412 | enum ast_tag ntag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24413 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24414 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24415 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24417 | ntag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24419 | switch (ntag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24420 | case AST_IDENT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24421 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24422 | if (tag != AST_ASSIGN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24423 | bcode_op_lit(bbuilder, OP_GET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24424 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24426 | V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24427 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24429 | fixup_post_op(bbuilder, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24430 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24431 | case AST_MEMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24432 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24433 | switch (ntag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24434 | case AST_MEMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24435 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24436 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24437 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24438 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24439 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24440 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24441 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24442 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24443 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24444 | /* unreachable, compilers are dumb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24445 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24447 | if (tag != AST_ASSIGN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24448 | bcode_op(bbuilder, OP_2DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24449 | bcode_op(bbuilder, OP_GET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24450 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24451 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24452 | V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24453 | bcode_op(bbuilder, OP_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24455 | fixup_post_op(bbuilder, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24456 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24457 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24458 | /* We end up here on expressions like `1 = 2;`, it's a ReferenceError */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24459 | rcode = v7_throwf(bbuilder->v7, REFERENCE_ERROR, "unexpected ast node"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24460 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24462 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24463 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24464 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24466 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24467 | * Walks through all declarations (`var` and `function`) in the current scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24468 | * and adds names of all of them to `bcode->ops`. Additionally, `function` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24469 | * declarations are compiled right here, since they're hoisted in JS. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24470 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24471 | static enum v7_err compile_local_vars(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24472 | struct ast *a, ast_off_t start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24473 | ast_off_t fvar) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24474 | ast_off_t next, fvar_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24475 | char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24476 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24477 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24478 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24479 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24480 | size_t names_end = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24481 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24483 | /* calculate `names_end`: offset at which names in `bcode->ops` end */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24484 | names_end = |
Marko Mikulicic |
0:c0ecb8bf28eb | 24485 | (size_t)(bcode_end_names(bbuilder->ops.buf, bbuilder->bcode->names_cnt) - |
Marko Mikulicic |
0:c0ecb8bf28eb | 24486 | bbuilder->ops.buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24488 | if (fvar != start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24489 | /* iterate all `AST_VAR`s in the current scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24490 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24491 | V7_CHECK_INTERNAL(fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 24492 | AST_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24494 | next = ast_get_skip(a, pos_after_tag, AST_VAR_NEXT_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24495 | if (next == pos_after_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24496 | next = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24499 | fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24500 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24501 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24502 | * iterate all `AST_VAR_DECL`s and `AST_FUNC_DECL`s in the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 24503 | * `AST_VAR` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24504 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24505 | while (fvar < fvar_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24506 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24507 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL || tag == AST_FUNC_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24508 | name = ast_get_inlined_data(a, pos_after_tag, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24509 | if (tag == AST_VAR_DECL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24510 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24511 | * it's a `var` declaration, so, skip the value for now, it'll be set |
Marko Mikulicic |
0:c0ecb8bf28eb | 24512 | * to `undefined` initially |
Marko Mikulicic |
0:c0ecb8bf28eb | 24513 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24514 | ast_skip_tree(a, &fvar); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24515 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24516 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24517 | * tag is an AST_FUNC_DECL: since functions in JS are hoisted, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24518 | * we compile it and put `OP_SET_VAR` directly here |
Marko Mikulicic |
0:c0ecb8bf28eb | 24519 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24520 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24521 | V7_TRY(compile_expr_builder(bbuilder, a, &fvar)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24522 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24523 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24524 | /* function declarations are stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24525 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24526 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24527 | * Note: the `is_stack_neutral` flag will be set by `compile_stmt` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24528 | * later, when it encounters `AST_FUNC_DECL` again. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24529 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24530 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24531 | V7_TRY(bcode_add_name(bbuilder, name, name_len, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24532 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24533 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24534 | if (next > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24535 | fvar = next - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24536 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24538 | } while (next != 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24539 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24540 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24541 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24542 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24544 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24545 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24546 | * Just like `compile_expr_builder`, but it takes additional argument: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24547 | *`for_call`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24548 | * If it's non-zero, the stack is additionally populated with `this` value |
Marko Mikulicic |
0:c0ecb8bf28eb | 24549 | * for call. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24550 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24551 | * If there is a refinement (a dot, or a subscript), then it'll be the |
Marko Mikulicic |
0:c0ecb8bf28eb | 24552 | * appropriate object. Otherwise, it's `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24553 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24554 | * In non-strict mode, `undefined` will be changed to Global Object at runtime, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24555 | * see `OP_CALL` handling in `eval_bcode()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24556 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24557 | V7_PRIVATE enum v7_err compile_expr_ext(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24558 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24559 | uint8_t for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24560 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24561 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24562 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24563 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24565 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24566 | case AST_MEMBER: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24567 | lit_t lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24568 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24569 | if (for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24570 | /* current TOS will be used as `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24571 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24572 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24573 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24574 | bcode_op(bbuilder, OP_GET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24575 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24576 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24578 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24579 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24580 | if (for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24581 | /* current TOS will be used as `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24582 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24583 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24584 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24585 | bcode_op(bbuilder, OP_GET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24586 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24587 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24588 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24589 | if (for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24590 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24591 | * `this` will be an `undefined` (but it may change to Global Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 24592 | * at runtime) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24593 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24594 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24596 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24597 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24598 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24599 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24601 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24602 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24603 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24605 | V7_PRIVATE enum v7_err compile_delete(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24606 | struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24607 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24608 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24609 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24610 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24612 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24613 | case AST_MEMBER: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24614 | /* Delete a specified property of an object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24615 | lit_t lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24616 | /* put an object to delete property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24617 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24618 | /* put a property name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24619 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24620 | bcode_op(bbuilder, OP_DELETE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24621 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24624 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24625 | /* Delete a specified property of an object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24626 | /* put an object to delete property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24627 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24628 | /* put a property name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24629 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24630 | bcode_op(bbuilder, OP_DELETE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24631 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24633 | case AST_IDENT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24634 | /* Delete the scope variable (or throw an error if strict mode) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24635 | if (!bbuilder->bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24636 | /* put a property name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24637 | bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24638 | bcode_op(bbuilder, OP_DELETE_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24639 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24640 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 24641 | v7_throwf(bbuilder->v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24642 | "Delete of an unqualified identifier in strict mode."); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24643 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24644 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24645 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24646 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24647 | case AST_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24648 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24649 | * `undefined` should actually be an undeletable property of the Global |
Marko Mikulicic |
0:c0ecb8bf28eb | 24650 | * Object, so, trying to delete it just yields `false` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24651 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24652 | bcode_op(bbuilder, OP_PUSH_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24653 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24655 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24656 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24657 | * For all other cases, we evaluate the expression given to `delete` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24658 | * for side effects, then drop the result, and yield `true` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24659 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24660 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24661 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24662 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24663 | bcode_op(bbuilder, OP_PUSH_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24664 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24665 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24667 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24668 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24669 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24671 | V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24672 | struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24673 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24674 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24675 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24676 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24678 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24679 | case AST_ADD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24680 | case AST_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24681 | case AST_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24682 | case AST_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24683 | case AST_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24684 | case AST_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24685 | case AST_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24686 | case AST_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24687 | case AST_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24688 | case AST_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24689 | case AST_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24690 | case AST_EQ_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24691 | case AST_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24692 | case AST_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24693 | case AST_NE_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24694 | case AST_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24695 | case AST_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24696 | case AST_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24697 | case AST_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24698 | case AST_INSTANCEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24699 | V7_TRY(compile_binary(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24700 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24701 | case AST_LOGICAL_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24702 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24703 | bcode_op(bbuilder, OP_LOGICAL_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24704 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24705 | case AST_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24706 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24707 | bcode_op(bbuilder, OP_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24708 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24709 | case AST_POSITIVE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24710 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24711 | bcode_op(bbuilder, OP_POS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24712 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24713 | case AST_NEGATIVE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24714 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24715 | bcode_op(bbuilder, OP_NEG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24716 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24717 | case AST_IDENT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24718 | bcode_op_lit(bbuilder, OP_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24719 | string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24720 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24721 | case AST_MEMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24722 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24723 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24724 | * These two are handled by the "extended" version of this function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24725 | * since we may need to put `this` value on stack, for "method pattern |
Marko Mikulicic |
0:c0ecb8bf28eb | 24726 | * invocation". |
Marko Mikulicic |
0:c0ecb8bf28eb | 24727 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24728 | * First of all, restore starting AST position, and then call extended |
Marko Mikulicic |
0:c0ecb8bf28eb | 24729 | * function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24730 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24731 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24732 | V7_TRY(compile_expr_ext(bbuilder, a, ppos, 0 /*not for call*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24733 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24734 | case AST_IN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24735 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24736 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24737 | bcode_op(bbuilder, OP_IN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24738 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24739 | case AST_TYPEOF: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24740 | ast_off_t lookahead = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24741 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24742 | if (tag == AST_IDENT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24743 | *ppos = lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24744 | bcode_op_lit(bbuilder, OP_SAFE_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24745 | string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24746 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24747 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24748 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24749 | bcode_op(bbuilder, OP_TYPEOF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24750 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24751 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24752 | case AST_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24753 | case AST_PREINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24754 | case AST_PREDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24755 | case AST_POSTINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24756 | case AST_POSTDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24757 | case AST_REM_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24758 | case AST_MUL_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24759 | case AST_DIV_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24760 | case AST_XOR_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24761 | case AST_PLUS_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24762 | case AST_MINUS_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24763 | case AST_OR_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24764 | case AST_AND_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24765 | case AST_LSHIFT_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24766 | case AST_RSHIFT_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24767 | case AST_URSHIFT_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24768 | V7_TRY(compile_assign(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24769 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24770 | case AST_COND: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24771 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24772 | * A ? B : C |
Marko Mikulicic |
0:c0ecb8bf28eb | 24773 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24774 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24775 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24776 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24777 | * JMP_FALSE false |
Marko Mikulicic |
0:c0ecb8bf28eb | 24778 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24779 | * JMP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 24780 | * false: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24781 | * <C> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24782 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24783 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24784 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24785 | bcode_off_t false_label, end_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24786 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24787 | false_label = bcode_op_target(bbuilder, OP_JMP_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24788 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24789 | end_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24790 | bcode_patch_target(bbuilder, false_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24791 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24792 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24793 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24794 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24795 | case AST_LOGICAL_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24796 | case AST_LOGICAL_AND: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24797 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24798 | * A && B |
Marko Mikulicic |
0:c0ecb8bf28eb | 24799 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24800 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24801 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24802 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24803 | * JMP_FALSE end |
Marko Mikulicic |
0:c0ecb8bf28eb | 24804 | * POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24805 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24806 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24807 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24808 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24809 | bcode_off_t end_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24810 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24811 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24812 | end_label = bcode_op_target( |
Marko Mikulicic |
0:c0ecb8bf28eb | 24813 | bbuilder, tag == AST_LOGICAL_AND ? OP_JMP_FALSE : OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24814 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24815 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24816 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24817 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24818 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24819 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24820 | * A, B, C |
Marko Mikulicic |
0:c0ecb8bf28eb | 24821 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24822 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24823 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24824 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24825 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24826 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24827 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24828 | * <C> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24829 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24830 | case AST_SEQ: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24831 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24832 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24833 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24834 | if (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24835 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24836 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24837 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24838 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24839 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24840 | case AST_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24841 | case AST_NEW: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24842 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24843 | * f() |
Marko Mikulicic |
0:c0ecb8bf28eb | 24844 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24845 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24846 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24847 | * PUSH_UNDEFINED (value for `this`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24848 | * GET_VAR "f" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24849 | * CHECK_CALL |
Marko Mikulicic |
0:c0ecb8bf28eb | 24850 | * CALL 0 args |
Marko Mikulicic |
0:c0ecb8bf28eb | 24851 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24852 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24853 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24854 | * f(a, b) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24855 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24856 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24857 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24858 | * PUSH_UNDEFINED (value for `this`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24859 | * GET_VAR "f" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24860 | * CHECK_CALL |
Marko Mikulicic |
0:c0ecb8bf28eb | 24861 | * GET_VAR "a" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24862 | * GET_VAR "b" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24863 | * CALL 2 args |
Marko Mikulicic |
0:c0ecb8bf28eb | 24864 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24865 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24866 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24867 | * o.f(a, b) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24868 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24869 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24870 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24871 | * GET_VAR "o" (so that `this` will be an `o`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24872 | * DUP (we'll also need `o` for GET below, so, duplicate it) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24873 | * PUSH_LIT "f" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24874 | * GET (get property "f" of the object "o") |
Marko Mikulicic |
0:c0ecb8bf28eb | 24875 | * CHECK_CALL |
Marko Mikulicic |
0:c0ecb8bf28eb | 24876 | * GET_VAR "a" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24877 | * GET_VAR "b" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24878 | * CALL 2 args |
Marko Mikulicic |
0:c0ecb8bf28eb | 24879 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24880 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24881 | int args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24882 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24884 | V7_TRY(compile_expr_ext(bbuilder, a, ppos, 1 /*for call*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24885 | bcode_op(bbuilder, OP_CHECK_CALL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24886 | for (args = 0; *ppos < end; args++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24887 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24889 | bcode_op(bbuilder, (tag == AST_CALL ? OP_CALL : OP_NEW)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24890 | if (args > 0x7f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24891 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "too many arguments"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24892 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24893 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24894 | bcode_op(bbuilder, (uint8_t) args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24895 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24897 | case AST_DELETE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24898 | V7_TRY(compile_delete(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24899 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24900 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24901 | case AST_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24902 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24903 | * {a:<B>, ...} |
Marko Mikulicic |
0:c0ecb8bf28eb | 24904 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24905 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24906 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24907 | * CREATE_OBJ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24908 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24909 | * PUSH_LIT "a" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24910 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24911 | * SET |
Marko Mikulicic |
0:c0ecb8bf28eb | 24912 | * POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24913 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 24914 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24916 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24917 | * Literal indices of property names of current object literal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24918 | * Needed for strict mode: we need to keep track of the added |
Marko Mikulicic |
0:c0ecb8bf28eb | 24919 | * properties, since duplicates are not allowed |
Marko Mikulicic |
0:c0ecb8bf28eb | 24920 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24921 | struct mbuf cur_literals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24922 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24923 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24924 | mbuf_init(&cur_literals, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24926 | bcode_op(bbuilder, OP_CREATE_OBJ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24927 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24928 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24929 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24930 | case AST_PROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24931 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24932 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24934 | /* disabled because we broke get_lit */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24935 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 24936 | if (bbuilder->bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24937 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24938 | * In strict mode, check for duplicate property names in |
Marko Mikulicic |
0:c0ecb8bf28eb | 24939 | * object literals |
Marko Mikulicic |
0:c0ecb8bf28eb | 24940 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24941 | char *plit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24942 | for (plit = (char *) cur_literals.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24943 | (char *) plit < cur_literals.buf + cur_literals.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24944 | plit++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24945 | const char *str1, *str2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24946 | size_t size1, size2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24947 | v7_val_t val1, val2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24948 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24949 | val1 = bcode_get_lit(bbuilder->bcode, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24950 | str1 = v7_get_string(bbuilder->v7, &val1, &size1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24952 | val2 = bcode_get_lit(bbuilder->bcode, *plit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24953 | str2 = v7_get_string(bbuilder->v7, &val2, &size2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24955 | if (size1 == size2 && memcmp(str1, str2, size1) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24956 | /* found already existing property of the same name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24957 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24958 | "duplicate data property in object literal " |
Marko Mikulicic |
0:c0ecb8bf28eb | 24959 | "is not allowed in strict mode"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24960 | V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24961 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24963 | mbuf_append(&cur_literals, &lit, sizeof(lit)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24964 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24965 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24966 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24967 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24968 | bcode_op(bbuilder, OP_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24969 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24970 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24971 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24972 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24973 | V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24974 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24975 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24976 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24977 | ast_object_clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24978 | mbuf_free(&cur_literals); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24979 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24980 | V7_THROW(rcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24982 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24983 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24984 | case AST_ARRAY: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24985 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24986 | * [<A>,,<B>,...] |
Marko Mikulicic |
0:c0ecb8bf28eb | 24987 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24988 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24989 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24990 | * CREATE_ARR |
Marko Mikulicic |
0:c0ecb8bf28eb | 24991 | * PUSH_ZERO |
Marko Mikulicic |
0:c0ecb8bf28eb | 24992 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24993 | * 2DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24994 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24995 | * SET |
Marko Mikulicic |
0:c0ecb8bf28eb | 24996 | * POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24997 | * PUSH_ONE |
Marko Mikulicic |
0:c0ecb8bf28eb | 24998 | * ADD |
Marko Mikulicic |
0:c0ecb8bf28eb | 24999 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25000 | * PUSH_ONE |
Marko Mikulicic |
0:c0ecb8bf28eb | 25001 | * ADD |
Marko Mikulicic |
0:c0ecb8bf28eb | 25002 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25003 | * 2DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25004 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25005 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25006 | * POP // tmp index |
Marko Mikulicic |
0:c0ecb8bf28eb | 25007 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25008 | * TODO(mkm): optimize this out. we can have more compact array push |
Marko Mikulicic |
0:c0ecb8bf28eb | 25009 | * that uses a special marker value for missing array elements |
Marko Mikulicic |
0:c0ecb8bf28eb | 25010 | * (which are not the same as undefined btw) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25011 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25012 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25013 | bcode_op(bbuilder, OP_CREATE_ARR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25014 | bcode_op(bbuilder, OP_PUSH_ZERO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25015 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25016 | ast_off_t lookahead = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25017 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25018 | if (tag != AST_NOP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25019 | bcode_op(bbuilder, OP_2DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25020 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25021 | bcode_op(bbuilder, OP_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25022 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25023 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25024 | *ppos = lookahead; /* skip nop */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25025 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25026 | bcode_op(bbuilder, OP_PUSH_ONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25027 | bcode_op(bbuilder, OP_ADD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25028 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25029 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25030 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25031 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25032 | case AST_FUNC: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25033 | lit_t flit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25035 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25036 | * Create half-done function: without scope and prototype. The real |
Marko Mikulicic |
0:c0ecb8bf28eb | 25037 | * function will be created from this one during bcode evaluation: see |
Marko Mikulicic |
0:c0ecb8bf28eb | 25038 | * `bcode_instantiate_function()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25039 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25040 | val_t funv = mk_js_function(bbuilder->v7, NULL, V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25042 | /* Create bcode in this half-done function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25043 | struct v7_js_function *func = get_js_function_struct(funv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25044 | func->bcode = (struct bcode *) calloc(1, sizeof(*bbuilder->bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25045 | bcode_init(func->bcode, bbuilder->bcode->strict_mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25046 | NULL /* will be set below */, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25047 | bcode_copy_filename_from(func->bcode, bbuilder->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25048 | retain_bcode(bbuilder->v7, func->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25049 | flit = bcode_add_lit(bbuilder, funv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25051 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25052 | V7_TRY(compile_function(v7, a, ppos, func->bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25053 | bcode_push_lit(bbuilder, flit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25054 | bcode_op(bbuilder, OP_FUNC_LIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25055 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25056 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25057 | case AST_THIS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25058 | bcode_op(bbuilder, OP_PUSH_THIS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25059 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25060 | case AST_VOID: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25061 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25062 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25063 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25064 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25065 | case AST_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25066 | bcode_op(bbuilder, OP_PUSH_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25067 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25068 | case AST_NOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25069 | case AST_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25070 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25071 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25072 | case AST_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25073 | bcode_op(bbuilder, OP_PUSH_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25074 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25075 | case AST_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25076 | bcode_op(bbuilder, OP_PUSH_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25077 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25078 | case AST_NUM: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25079 | double dv = ast_get_num(a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25080 | if (dv == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25081 | bcode_op(bbuilder, OP_PUSH_ZERO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25082 | } else if (dv == 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25083 | bcode_op(bbuilder, OP_PUSH_ONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25084 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25085 | bcode_push_lit(bbuilder, bcode_add_lit(bbuilder, v7_mk_number(v7, dv))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25086 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25087 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25089 | case AST_STRING: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25090 | bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25091 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25092 | case AST_REGEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25093 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 25094 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25095 | lit_t tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25096 | rcode = regexp_lit(bbuilder, a, pos_after_tag, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25097 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25098 | rcode = V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25099 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25102 | bcode_push_lit(bbuilder, tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25103 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25104 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25105 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 25106 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 25107 | v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Regexp support is disabled"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25108 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25109 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 25110 | case AST_LABEL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25111 | case AST_LABELED_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25112 | case AST_LABELED_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25113 | /* TODO(dfrank): implement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25114 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25115 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25116 | case AST_WITH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25117 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25118 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25119 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25120 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25121 | * We end up here if the AST is broken. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25122 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25123 | * It might be appropriate to return `V7_INTERNAL_ERROR` here, but since |
Marko Mikulicic |
0:c0ecb8bf28eb | 25124 | * we might receive AST from network or something, we just interpret |
Marko Mikulicic |
0:c0ecb8bf28eb | 25125 | * it as SyntaxError. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25126 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25127 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown ast node %d", |
Marko Mikulicic |
0:c0ecb8bf28eb | 25128 | (int) tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25129 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25130 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25131 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25132 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25133 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25135 | V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25136 | struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25138 | V7_PRIVATE enum v7_err compile_stmts(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25139 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25140 | ast_off_t end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25141 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25142 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25144 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25145 | V7_TRY(compile_stmt(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25146 | if (!bbuilder->v7->is_stack_neutral) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25147 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25148 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25149 | bbuilder->v7->is_stack_neutral = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25150 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25151 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25152 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25153 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25156 | V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25157 | struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25158 | ast_off_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25159 | enum ast_tag tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25160 | ast_off_t cond, pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25161 | bcode_off_t body_target, body_label, cond_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25162 | struct mbuf case_labels; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25163 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25164 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25166 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25167 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25168 | mbuf_init(&case_labels, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25170 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25171 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25172 | * if(E) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25173 | * BT... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25174 | * } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25175 | * BF... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25176 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25177 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25178 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25179 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25180 | * <E> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25181 | * JMP_FALSE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25182 | * <BT> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25183 | * JMP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25184 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25185 | * <BF> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25186 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25187 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25188 | * If else clause is omitted, it will emit output equivalent to: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25189 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25190 | * if(E) {BT} else undefined; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25191 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25192 | case AST_IF: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25193 | ast_off_t if_false; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25194 | bcode_off_t end_label, if_false_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25195 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25196 | if_false = ast_get_skip(a, pos_after_tag, AST_END_IF_TRUE_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25198 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25199 | if_false_label = bcode_op_target(bbuilder, OP_JMP_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25201 | /* body if true */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25202 | V7_TRY(compile_stmts(bbuilder, a, ppos, if_false)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25204 | if (if_false != end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25205 | /* `else` branch is present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25206 | end_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25207 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25208 | /* will jump here if `false` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25209 | bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25210 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25211 | /* body if false */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25212 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25214 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25215 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25216 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25217 | * `else` branch is not present: just remember where we should |
Marko Mikulicic |
0:c0ecb8bf28eb | 25218 | * jump in case of `false` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25219 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25220 | bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25221 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25223 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25224 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25225 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25226 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25227 | * while(C) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25228 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25229 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25230 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25231 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25232 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25233 | * TRY_PUSH_LOOP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25234 | * JMP cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25235 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25236 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25237 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25238 | * <C> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25239 | * JMP_TRUE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25240 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25241 | * JMP_IF_CONTINUE cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25242 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25243 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25244 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25245 | case AST_WHILE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25246 | bcode_off_t end_label, continue_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25248 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25249 | cond = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25250 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25252 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25253 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25254 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25255 | * Condition check is at the end of the loop, this layout |
Marko Mikulicic |
0:c0ecb8bf28eb | 25256 | * reduces the number of jumps in the steady state. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25257 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25258 | cond_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25259 | body_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25261 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25263 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25264 | bcode_patch_target(bbuilder, cond_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25265 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25266 | V7_TRY(compile_expr_builder(bbuilder, a, &cond)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25267 | body_label = bcode_op_target(bbuilder, OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25268 | bcode_patch_target(bbuilder, body_label, body_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25270 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25271 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25272 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25273 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25275 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25276 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25277 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25278 | case AST_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25279 | bcode_op(bbuilder, OP_BREAK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25280 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25281 | case AST_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25282 | bcode_op(bbuilder, OP_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25283 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25284 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25285 | * Frame objects (`v7->vals.call_stack`) contain one more hidden property: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25286 | * `____t`, which is an array of offsets in bcode. Each element of the array |
Marko Mikulicic |
0:c0ecb8bf28eb | 25287 | * is an offset of either `catch` or `finally` block (distinguished by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 25288 | * tag: `OFFSET_TAG_CATCH` or `OFFSET_TAG_FINALLY`). Let's call this array |
Marko Mikulicic |
0:c0ecb8bf28eb | 25289 | * as a "try stack". When evaluator enters new `try` block, it adds |
Marko Mikulicic |
0:c0ecb8bf28eb | 25290 | * appropriate offset(s) at the top of "try stack", and when we unwind the |
Marko Mikulicic |
0:c0ecb8bf28eb | 25291 | * stack, we can "pop" offsets from "try stack" at each level. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25292 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25293 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25294 | * TRY_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25295 | * } catch (e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25296 | * CATCH_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25297 | * } finally { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25298 | * FIN_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25299 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25300 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25301 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25302 | * OP_TRY_PUSH_FINALLY finally |
Marko Mikulicic |
0:c0ecb8bf28eb | 25303 | * OP_TRY_PUSH_CATCH catch |
Marko Mikulicic |
0:c0ecb8bf28eb | 25304 | * <TRY_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25305 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25306 | * JMP finally |
Marko Mikulicic |
0:c0ecb8bf28eb | 25307 | * catch: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25308 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25309 | * OP_ENTER_CATCH <e> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25310 | * <CATCH_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25311 | * OP_EXIT_CATCH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25312 | * finally: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25313 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25314 | * <FIN_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25315 | * OP_AFTER_FINALLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 25316 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25317 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 25318 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25319 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25320 | * TRY_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25321 | * } catch (e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25322 | * CATCH_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25323 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25324 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25325 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25326 | * OP_TRY_PUSH_CATCH catch |
Marko Mikulicic |
0:c0ecb8bf28eb | 25327 | * <TRY_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25328 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25329 | * JMP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25330 | * catch: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25331 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25332 | * OP_ENTER_CATCH <e> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25333 | * <CATCH_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25334 | * OP_EXIT_CATCH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25335 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25336 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25337 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 25338 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25339 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25340 | * TRY_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25341 | * } finally { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25342 | * FIN_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25343 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25344 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25345 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25346 | * OP_TRY_PUSH_FINALLY finally |
Marko Mikulicic |
0:c0ecb8bf28eb | 25347 | * <TRY_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25348 | * finally: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25349 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25350 | * <FIN_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25351 | * OP_AFTER_FINALLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 25352 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25353 | case AST_TRY: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25354 | ast_off_t acatch, afinally; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25355 | bcode_off_t finally_label, catch_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25357 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25358 | acatch = ast_get_skip(a, pos_after_tag, AST_TRY_CATCH_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25359 | afinally = ast_get_skip(a, pos_after_tag, AST_TRY_FINALLY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25361 | if (afinally != end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25362 | /* `finally` clause is present: push its offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25363 | finally_label = bcode_op_target(bbuilder, OP_TRY_PUSH_FINALLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25366 | if (acatch != afinally) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25367 | /* `catch` clause is present: push its offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25368 | catch_label = bcode_op_target(bbuilder, OP_TRY_PUSH_CATCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25371 | /* compile statements of `try` block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25372 | V7_TRY(compile_stmts(bbuilder, a, ppos, acatch)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25374 | if (acatch != afinally) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25375 | /* `catch` clause is present: compile it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25376 | bcode_off_t after_catch_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25378 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25379 | * pop offset pushed by OP_TRY_PUSH_CATCH, and jump over the `catch` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25380 | * block |
Marko Mikulicic |
0:c0ecb8bf28eb | 25381 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25382 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25383 | after_catch_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25385 | /* --- catch --- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25387 | /* in case of exception in the `try` block above, we'll get here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25388 | bcode_patch_target(bbuilder, catch_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25390 | /* pop offset pushed by OP_TRY_PUSH_CATCH */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25391 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25393 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25394 | * retrieve identifier where to store thrown error, and make sure |
Marko Mikulicic |
0:c0ecb8bf28eb | 25395 | * it is actually an indentifier (AST_IDENT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25396 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25397 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25398 | V7_CHECK(tag == AST_IDENT, V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25400 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25401 | * when we enter `catch` block, the TOS contains thrown value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25402 | * We should create private frame for the `catch` clause, and populate |
Marko Mikulicic |
0:c0ecb8bf28eb | 25403 | * a variable with the thrown value there. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25404 | * The `OP_ENTER_CATCH` opcode does just that. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25405 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25406 | bcode_op_lit(bbuilder, OP_ENTER_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25407 | string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25409 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25410 | * compile statements until the end of `catch` clause |
Marko Mikulicic |
0:c0ecb8bf28eb | 25411 | * (`afinally` points to the end of the `catch` clause independently |
Marko Mikulicic |
0:c0ecb8bf28eb | 25412 | * of whether the `finally` clause is present) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25413 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25414 | V7_TRY(compile_stmts(bbuilder, a, ppos, afinally)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25415 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25416 | /* pop private frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25417 | bcode_op(bbuilder, OP_EXIT_CATCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25419 | bcode_patch_target(bbuilder, after_catch_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25420 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25422 | if (afinally != end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25423 | /* `finally` clause is present: compile it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25425 | /* --- finally --- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25427 | /* after the `try` block above executes, we'll get here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25428 | bcode_patch_target(bbuilder, finally_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25430 | /* pop offset pushed by OP_TRY_PUSH_FINALLY */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25431 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25432 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25433 | /* compile statements until the end of `finally` clause */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25434 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25436 | bcode_op(bbuilder, OP_AFTER_FINALLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25437 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25438 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25439 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25440 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25443 | case AST_THROW: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25444 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25445 | bcode_op(bbuilder, OP_THROW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25446 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25447 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25449 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25450 | * switch(E) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25451 | * default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25452 | * D... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25453 | * case C1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25454 | * B1... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25455 | * case C2: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25456 | * B2... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25457 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25458 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25459 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25460 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25461 | * TRY_PUSH_SWITCH end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25462 | * <E> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25463 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25464 | * <C1> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25465 | * EQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25466 | * JMP_TRUE_DROP l1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 25467 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25468 | * <C2> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25469 | * EQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25470 | * JMP_TRUE_DROP l2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 25471 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25472 | * JMP dfl |
Marko Mikulicic |
0:c0ecb8bf28eb | 25473 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25474 | * dfl: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25475 | * <D> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25476 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25477 | * l1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25478 | * <B1> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25479 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25480 | * l2: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25481 | * <B2> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25482 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25483 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25484 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25485 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25486 | * If the default case is missing we treat it as if had an empty body and |
Marko Mikulicic |
0:c0ecb8bf28eb | 25487 | * placed in last position (i.e. `dfl` label is replaced with `end`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 25488 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25489 | * Before emitting a case/default block (except the first one) we have to |
Marko Mikulicic |
0:c0ecb8bf28eb | 25490 | * drop the TOS resulting from evaluating the last expression |
Marko Mikulicic |
0:c0ecb8bf28eb | 25491 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25492 | case AST_SWITCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25493 | bcode_off_t dfl_label, end_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25494 | ast_off_t case_end, case_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25495 | enum ast_tag case_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25496 | int i, has_default = 0, cases = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25497 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25498 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25499 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25500 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_SWITCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25502 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25503 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25504 | case_start = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25505 | /* first pass: evaluate case expression and generate jump table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25506 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25507 | case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25508 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25510 | case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25512 | switch (case_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25513 | case AST_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25514 | /* default jump table entry must be the last one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25515 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25516 | case AST_CASE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25517 | bcode_off_t case_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25518 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25519 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25520 | bcode_op(bbuilder, OP_EQ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25521 | case_label = bcode_op_target(bbuilder, OP_JMP_TRUE_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25522 | cases++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25523 | mbuf_append(&case_labels, &case_label, sizeof(case_label)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25524 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25525 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25526 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25527 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25528 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25529 | *ppos = case_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25530 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25532 | /* jmp table epilogue: unconditional jump to default case */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25533 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25534 | dfl_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25536 | *ppos = case_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25537 | /* second pass: emit case bodies and patch jump table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25538 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25539 | for (i = 0; *ppos < end;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25540 | case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25541 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25542 | assert(i <= cases); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25544 | case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25546 | switch (case_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25547 | case AST_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25548 | has_default = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25549 | bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25550 | V7_TRY(compile_stmts(bbuilder, a, ppos, case_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25551 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25552 | case AST_CASE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25553 | bcode_off_t case_label = ((bcode_off_t *) case_labels.buf)[i++]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25554 | bcode_patch_target(bbuilder, case_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25555 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25556 | V7_TRY(compile_stmts(bbuilder, a, ppos, case_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25557 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25558 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25559 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25560 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25561 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25563 | *ppos = case_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25564 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25565 | mbuf_free(&case_labels); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25567 | if (!has_default) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25568 | bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25569 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25571 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25572 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25574 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25575 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25576 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25577 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25578 | * for(INIT,COND,IT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25579 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25580 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25581 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25582 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25583 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25584 | * <INIT> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25585 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25586 | * TRY_PUSH_LOOP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25587 | * JMP cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25588 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25589 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25590 | * next: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25591 | * <IT> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25592 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25593 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25594 | * <COND> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25595 | * JMP_TRUE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25596 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25597 | * JMP_IF_CONTINUE next |
Marko Mikulicic |
0:c0ecb8bf28eb | 25598 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25599 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25600 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25601 | case AST_FOR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25602 | ast_off_t iter, body, lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25603 | bcode_off_t end_label, continue_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25604 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25605 | body = ast_get_skip(a, pos_after_tag, AST_FOR_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25606 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25607 | lookahead = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25608 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25609 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25610 | * Support for `var` declaration in INIT |
Marko Mikulicic |
0:c0ecb8bf28eb | 25611 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25612 | if (tag == AST_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25613 | ast_off_t fvar_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25614 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25616 | *ppos = lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25617 | fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25618 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25619 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25620 | * Iterate through all vars in the given `var` declaration: they are |
Marko Mikulicic |
0:c0ecb8bf28eb | 25621 | * just like assigments here |
Marko Mikulicic |
0:c0ecb8bf28eb | 25622 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25623 | while (*ppos < fvar_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25624 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25625 | /* Only var declarations are allowed (not function declarations) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25626 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25627 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25628 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25630 | /* Just like an assigment */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25631 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25633 | /* INIT is stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25634 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25636 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25637 | /* normal expression in INIT (not `var` declaration) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25638 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25639 | /* INIT is stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25640 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25642 | cond = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25643 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25644 | iter = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25645 | *ppos = body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25646 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25647 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25648 | cond_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25649 | body_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25650 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25652 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25654 | V7_TRY(compile_expr_builder(bbuilder, a, &iter)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25655 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25656 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25657 | bcode_patch_target(bbuilder, cond_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25659 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25660 | * Handle for(INIT;;ITER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25661 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25662 | lookahead = cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25663 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25664 | if (tag == AST_NOP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25665 | bcode_op(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25666 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25667 | V7_TRY(compile_expr_builder(bbuilder, a, &cond)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25668 | bcode_op(bbuilder, OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25669 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25670 | body_label = bcode_add_target(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25671 | bcode_patch_target(bbuilder, body_label, body_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25672 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25674 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25675 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25676 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25677 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25679 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25680 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25681 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25682 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25683 | * for(I in O) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25684 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25685 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25686 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25687 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25688 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25689 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25690 | * <O> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25691 | * SWAP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25692 | * STASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25693 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25694 | * PUSH_PROP_ITER_CTX # push initial iteration context |
Marko Mikulicic |
0:c0ecb8bf28eb | 25695 | * TRY_PUSH_LOOP brend |
Marko Mikulicic |
0:c0ecb8bf28eb | 25696 | * loop: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25697 | * NEXT_PROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25698 | * JMP_FALSE end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25699 | * SET_VAR <I> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25700 | * UNSTASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25701 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25702 | * next: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25703 | * STASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25704 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25705 | * JMP loop |
Marko Mikulicic |
0:c0ecb8bf28eb | 25706 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25707 | * UNSTASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25708 | * JMP try_pop: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25709 | * brend: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25710 | * # got here after a `break` or `continue` from a loop body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25711 | * JMP_IF_CONTINUE next |
Marko Mikulicic |
0:c0ecb8bf28eb | 25712 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25713 | * # we're not going to `continue`, so, need to remove an |
Marko Mikulicic |
0:c0ecb8bf28eb | 25714 | * # extra stuff that was needed for the NEXT_PROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25715 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25716 | * SWAP_DROP # drop iteration context |
Marko Mikulicic |
0:c0ecb8bf28eb | 25717 | * SWAP_DROP # drop <O> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25718 | * SWAP_DROP # drop the value preceding the loop |
Marko Mikulicic |
0:c0ecb8bf28eb | 25719 | * try_pop: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25720 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25721 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25722 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25723 | case AST_FOR_IN: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25724 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25725 | bcode_off_t loop_label, loop_target, end_label, brend_label, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25726 | continue_label, pop_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25727 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25729 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25730 | /* TODO(mkm) accept any l-value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25731 | if (tag == AST_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25732 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25733 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25734 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25735 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25736 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25737 | V7_CHECK_INTERNAL(tag == AST_IDENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25738 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25739 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25741 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25742 | * preserve previous statement value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25743 | * We need to feed the previous value into the stash |
Marko Mikulicic |
0:c0ecb8bf28eb | 25744 | * because it's required for the loop steady state. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25745 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25746 | * The stash register is required to simplify the steady state stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 25747 | * management, in particular the removal of value in 3rd position in case |
Marko Mikulicic |
0:c0ecb8bf28eb | 25748 | * a of not taken exit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25749 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25750 | * TODO(mkm): consider having a stash OP that moves a value to the stash |
Marko Mikulicic |
0:c0ecb8bf28eb | 25751 | * register instead of copying it. The current behaviour has been |
Marko Mikulicic |
0:c0ecb8bf28eb | 25752 | * optimized for the `assign` use case which seems more common. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25753 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25754 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25755 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25756 | bcode_op(bbuilder, OP_SWAP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25757 | bcode_op(bbuilder, OP_STASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25758 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25760 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25761 | * OP_NEXT_PROP needs the iteration context, let's push the initial one. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25762 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25763 | bcode_op(bbuilder, OP_PUSH_PROP_ITER_CTX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25764 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25765 | brend_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25767 | /* loop: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25768 | loop_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25770 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25771 | * The loop stead state begins with the following stack layout: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25772 | * `( S:v o h )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25773 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25775 | bcode_op(bbuilder, OP_NEXT_PROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25776 | end_label = bcode_op_target(bbuilder, OP_JMP_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25777 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25779 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25780 | * The stash register contains the value of the previous statement, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25781 | * being it the statement before the for..in statement or |
Marko Mikulicic |
0:c0ecb8bf28eb | 25782 | * the previous iteration. We move it to the data stack. It will |
Marko Mikulicic |
0:c0ecb8bf28eb | 25783 | * be replaced by the values of the body statements as usual. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25784 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25785 | bcode_op(bbuilder, OP_UNSTASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25786 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25787 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25788 | * This node is always a NOP, for compatibility |
Marko Mikulicic |
0:c0ecb8bf28eb | 25789 | * with the layout of the AST_FOR node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25790 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25791 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25793 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25794 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25795 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25797 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25798 | * Save the last body statement. If next evaluation of NEXT_PROP returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 25799 | * false, we'll unstash it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25800 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25801 | bcode_op(bbuilder, OP_STASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25802 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25804 | loop_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25805 | bcode_patch_target(bbuilder, loop_label, loop_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25806 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25807 | /* end: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25808 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25809 | bcode_op(bbuilder, OP_UNSTASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25811 | pop_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25813 | /* brend: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25814 | bcode_patch_target(bbuilder, brend_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25816 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25817 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25818 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25819 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25820 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25821 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25823 | /* try_pop: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25824 | bcode_patch_target(bbuilder, pop_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25826 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25828 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25829 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25830 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25831 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25832 | * do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25833 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25834 | * } while(COND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25835 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25836 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25837 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25838 | * TRY_PUSH_LOOP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25839 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25840 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25841 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25842 | * <COND> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25843 | * JMP_TRUE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25844 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25845 | * JMP_IF_CONTINUE cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25846 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25847 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25848 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25849 | case AST_DOWHILE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25850 | bcode_off_t end_label, continue_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25851 | end = ast_get_skip(a, pos_after_tag, AST_DO_WHILE_COND_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25852 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25853 | body_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25854 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25855 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25856 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25857 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25858 | body_label = bcode_op_target(bbuilder, OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25859 | bcode_patch_target(bbuilder, body_label, body_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25861 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25862 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25863 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25864 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25866 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25867 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25868 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25869 | case AST_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25870 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25871 | * Var decls are hoisted when the function frame is created. Vars |
Marko Mikulicic |
0:c0ecb8bf28eb | 25872 | * declared inside a `with` or `catch` block belong to the function |
Marko Mikulicic |
0:c0ecb8bf28eb | 25873 | * lexical scope, and although those clauses create an inner frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 25874 | * no new variables should be created in it. A var decl thus |
Marko Mikulicic |
0:c0ecb8bf28eb | 25875 | * behaves as a normal assignment at runtime. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25876 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25877 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25878 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25879 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25880 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25881 | if (tag == AST_FUNC_DECL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25882 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25883 | * function declarations are already set during hoisting (see |
Marko Mikulicic |
0:c0ecb8bf28eb | 25884 | * `compile_local_vars()`), so, skip it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25885 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25886 | * Plus, they are stack-neutral, so don't forget to set |
Marko Mikulicic |
0:c0ecb8bf28eb | 25887 | * `is_stack_neutral`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25888 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25889 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25890 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25891 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25892 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25893 | * compile `var` declaration: basically it looks similar to an |
Marko Mikulicic |
0:c0ecb8bf28eb | 25894 | * assignment, but it differs from an assignment is that it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 25895 | * stack-neutral: `1; var a = 5;` yields `1`, not `5`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25896 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25897 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25898 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25899 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25900 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25901 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25902 | /* `var` declaration is stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25903 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25904 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25906 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25907 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25908 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25909 | case AST_RETURN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25910 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25911 | bcode_op(bbuilder, OP_RET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25912 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25913 | case AST_VALUE_RETURN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25914 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25915 | bcode_op(bbuilder, OP_RET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25916 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25917 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25918 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25919 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25922 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25923 | mbuf_free(&case_labels); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25924 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25925 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25927 | static enum v7_err compile_body(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25928 | ast_off_t start, ast_off_t end, ast_off_t body, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25929 | ast_off_t fvar, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25930 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25931 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25933 | #ifndef V7_FORCE_STRICT_MODE |
Marko Mikulicic |
0:c0ecb8bf28eb | 25934 | /* check 'use strict' */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25935 | if (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25936 | ast_off_t tmp_pos = body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25937 | if (fetch_tag(v7, bbuilder, a, &tmp_pos, NULL) == AST_USE_STRICT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25938 | bbuilder->bcode->strict_mode = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25939 | /* move `body` offset, effectively removing `AST_USE_STRICT` from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25940 | body = tmp_pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25942 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25943 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 25944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25945 | /* put initial value for the function body execution */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25946 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25948 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25949 | * populate `bcode->ops` with function's local variable names. Note that we |
Marko Mikulicic |
0:c0ecb8bf28eb | 25950 | * should do this *after* `OP_PUSH_UNDEFINED`, since `compile_local_vars` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25951 | * emits code that assigns the hoisted functions to local variables, and |
Marko Mikulicic |
0:c0ecb8bf28eb | 25952 | * those statements assume that the stack contains `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25953 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25954 | V7_TRY(compile_local_vars(bbuilder, a, start, fvar)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25956 | /* compile body */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25957 | *ppos = body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25958 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25960 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25961 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25964 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25965 | * Compiles a given script and populates a bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25966 | * The AST must start with an AST_SCRIPT node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25967 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25968 | V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25969 | struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25970 | ast_off_t pos_after_tag, end, fvar, pos = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25971 | int saved_line_no = v7->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25972 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25973 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25974 | enum ast_tag tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25975 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25976 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25977 | v7->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25979 | tag = fetch_tag(v7, &bbuilder, a, &pos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25981 | /* first tag should always be AST_SCRIPT */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25982 | assert(tag == AST_SCRIPT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25983 | (void) tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25984 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25985 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25986 | fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25988 | V7_TRY(compile_body(&bbuilder, a, pos_after_tag - 1, end, pos /* body */, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25989 | fvar, &pos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25991 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25993 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25995 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25996 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25997 | fprintf(stderr, "--- script ---\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25998 | dump_bcode(v7, stderr, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25999 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26000 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26002 | v7->line_no = saved_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26003 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26004 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26005 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26007 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26008 | * Compiles a given function and populates a bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26009 | * The AST must contain an AST_FUNC node at offset ast_off. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26010 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26011 | V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26012 | ast_off_t *ppos, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26013 | ast_off_t pos_after_tag, start, end, body, fvar; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26014 | const char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26015 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26016 | size_t args_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26017 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26018 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26019 | enum ast_tag tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26020 | size_t names_end = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26021 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26022 | tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26023 | start = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26024 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26025 | (void) tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26026 | assert(tag == AST_FUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26027 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26028 | body = ast_get_skip(a, pos_after_tag, AST_FUNC_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26029 | fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26031 | /* retrieve function name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26032 | tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26033 | if (tag == AST_IDENT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26034 | /* function name is provided */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26035 | name = ast_get_inlined_data(a, pos_after_tag, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26036 | V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26037 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26038 | /* no name: anonymous function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26039 | V7_TRY(bcode_add_name(&bbuilder, "", 0, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26040 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26042 | /* retrieve function's argument names */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26043 | for (args_cnt = 0; *ppos < body; args_cnt++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26044 | if (args_cnt > V7_ARGS_CNT_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26045 | /* too many arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26046 | rcode = v7_throwf(v7, SYNTAX_ERROR, "Too many arguments"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26047 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26050 | tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26051 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26052 | * TODO(dfrank): it's not actually an internal error, we get here if |
Marko Mikulicic |
0:c0ecb8bf28eb | 26053 | * we compile e.g. the following: (function(1){}) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26054 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26055 | V7_CHECK_INTERNAL(tag == AST_IDENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26056 | name = ast_get_inlined_data(a, pos_after_tag, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26057 | V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26060 | bcode->args_cnt = args_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26061 | bcode->func_name_present = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26063 | V7_TRY(compile_body(&bbuilder, a, start, end, body, fvar, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26065 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26066 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26067 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26068 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 26069 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26070 | fprintf(stderr, "--- function ---\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26071 | dump_bcode(v7, stderr, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26072 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26073 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26074 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26075 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26076 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26078 | V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26079 | ast_off_t *ppos, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26080 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26081 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26082 | int saved_line_no = v7->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26084 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26085 | v7->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26086 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26087 | rcode = compile_expr_builder(&bbuilder, a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26088 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26089 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26090 | v7->line_no = saved_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26091 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26094 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26095 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 26096 | #line 1 "v7/src/stdlib.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 26097 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26098 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26099 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 26100 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 26101 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26103 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26104 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26105 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26106 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26107 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26108 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26109 | /* Amalgamated: #include "v7/src/stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26110 | /* Amalgamated: #include "v7/src/std_array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26111 | /* Amalgamated: #include "v7/src/std_boolean.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26112 | /* Amalgamated: #include "v7/src/std_date.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26113 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26114 | /* Amalgamated: #include "v7/src/std_function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26115 | /* Amalgamated: #include "v7/src/std_json.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26116 | /* Amalgamated: #include "v7/src/std_math.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26117 | /* Amalgamated: #include "v7/src/std_number.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26118 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26119 | /* Amalgamated: #include "v7/src/std_regex.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26120 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26121 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26122 | /* Amalgamated: #include "v7/src/js_stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26123 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26124 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26125 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26126 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26128 | #ifdef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26129 | void print_str(const char *str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26130 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26132 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26133 | V7_PRIVATE enum v7_err Std_print(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26134 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26135 | int i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26136 | val_t v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26138 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26140 | for (i = 0; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26141 | v = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26142 | if (v7_is_string(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26143 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26144 | const char *s = v7_get_string(v7, &v, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26145 | printf("%.*s", (int) n, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26146 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26147 | v7_print(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26148 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26149 | printf(" "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26150 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26151 | printf(ENDL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26153 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26156 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26157 | V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26158 | int is_json, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26159 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26160 | char buf[100], *p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26161 | struct v7_exec_opts opts; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26162 | memset(&opts, 0x00, sizeof(opts)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26163 | opts.filename = "Eval'd code"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26164 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26165 | if (arg != V7_UNDEFINED) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26166 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26167 | rcode = to_string(v7, arg, NULL, buf, sizeof(buf), &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26168 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26169 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26170 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26172 | /* Fit null terminating byte and quotes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26173 | if (len >= sizeof(buf) - 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26174 | /* Buffer is not large enough. Allocate a bigger one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26175 | p = (char *) malloc(len + 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26176 | rcode = to_string(v7, arg, NULL, p, len + 2, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26177 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26178 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26179 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26180 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26182 | v7_set_gc_enabled(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26183 | if (is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26184 | opts.is_json = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26185 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26186 | opts.this_obj = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26187 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26188 | rcode = v7_exec_opt(v7, p, &opts, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26189 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26190 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26191 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26194 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26195 | if (p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26196 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26197 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26199 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26201 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26202 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26203 | V7_PRIVATE enum v7_err Std_eval(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26204 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26205 | v7_val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26206 | return std_eval(v7, arg, this_obj, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26207 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26209 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26210 | V7_PRIVATE enum v7_err Std_parseInt(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26211 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26212 | v7_val_t arg0 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26213 | v7_val_t arg1 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26214 | long sign = 1, base, n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26215 | char buf[20], *p = buf, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26216 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26217 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26218 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26219 | arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26220 | arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26222 | rcode = to_string(v7, arg0, &arg0, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26223 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26224 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26225 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26226 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26227 | rcode = to_number_v(v7, arg1, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26228 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26229 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26230 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26232 | if (is_finite(v7, arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26233 | base = v7_get_double(v7, arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26234 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26235 | base = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26236 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26238 | if (base == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26239 | base = 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26240 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26242 | if (base < 2 || base > 36) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26243 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26244 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26245 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26246 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26247 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26248 | size_t str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26249 | p = (char *) v7_get_string(v7, &arg0, &str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26252 | /* Strip leading whitespaces */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26253 | while (*p != '\0' && isspace(*(unsigned char *) p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26254 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26255 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26257 | if (*p == '+') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26258 | sign = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26259 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26260 | } else if (*p == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26261 | sign = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26262 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26263 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26264 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26265 | if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26266 | base = 16; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26267 | p += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26268 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26270 | n = strtol(p, &end, base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26272 | *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, n * sign); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26274 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26275 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26276 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26278 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26279 | V7_PRIVATE enum v7_err Std_parseFloat(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26280 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26281 | v7_val_t arg0 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26282 | char buf[20], *p = buf, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26283 | double result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26285 | rcode = to_primitive(v7, v7_arg(v7, 0), V7_TO_PRIMITIVE_HINT_NUMBER, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26286 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26287 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26288 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26290 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26291 | size_t str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26292 | p = (char *) v7_get_string(v7, &arg0, &str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26293 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26294 | rcode = to_string(v7, arg0, NULL, buf, sizeof(buf), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26295 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26296 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26297 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26298 | buf[sizeof(buf) - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26299 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26300 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26301 | while (*p != '\0' && isspace(*(unsigned char *) p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26302 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26303 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26305 | result = cs_strtod(p, &end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26307 | *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26309 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26310 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26311 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26312 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26313 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26314 | V7_PRIVATE enum v7_err Std_isNaN(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26315 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26316 | v7_val_t arg0 = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26317 | rcode = to_number_v(v7, v7_arg(v7, 0), &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26318 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26319 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26322 | *res = v7_mk_boolean(v7, isnan(v7_get_double(v7, arg0))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26324 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26325 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26326 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26328 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26329 | V7_PRIVATE enum v7_err Std_isFinite(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26330 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26331 | v7_val_t arg0 = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26333 | rcode = to_number_v(v7, v7_arg(v7, 0), &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26334 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26335 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26336 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26338 | *res = v7_mk_boolean(v7, is_finite(v7, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26340 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26341 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26344 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26345 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26346 | V7_PRIVATE enum v7_err Std_exit(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26347 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26348 | long exit_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26350 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26352 | rcode = to_long(v7, v7_arg(v7, 0), 0, &exit_code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26353 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26354 | /* `to_long` has thrown, so, will return 1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26355 | exit_code = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26356 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26357 | exit(exit_code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26358 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26359 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26361 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26362 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26363 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26364 | * Initialize standard library. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26365 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26366 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 26367 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 26368 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26369 | /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26370 | v7_prop_attr_desc_t attr_internal = |
Marko Mikulicic |
0:c0ecb8bf28eb | 26371 | (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26373 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26374 | * Ensure the first call to v7_mk_value will use a null proto: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26375 | * {}.__proto__.__proto__ == null |
Marko Mikulicic |
0:c0ecb8bf28eb | 26376 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26377 | v7->vals.object_prototype = mk_object(v7, V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26378 | v7->vals.array_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26379 | v7->vals.boolean_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26380 | v7->vals.string_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26381 | v7->vals.regexp_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26382 | v7->vals.number_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26383 | v7->vals.error_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26384 | v7->vals.global_object = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26385 | v7->vals.date_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26386 | v7->vals.function_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26387 | v7->vals.proxy_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26389 | set_method(v7, v7->vals.global_object, "eval", Std_eval, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26390 | set_method(v7, v7->vals.global_object, "print", Std_print, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26391 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26392 | set_method(v7, v7->vals.global_object, "exit", Std_exit, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26393 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26394 | set_method(v7, v7->vals.global_object, "parseInt", Std_parseInt, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26395 | set_method(v7, v7->vals.global_object, "parseFloat", Std_parseFloat, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26396 | set_method(v7, v7->vals.global_object, "isNaN", Std_isNaN, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26397 | set_method(v7, v7->vals.global_object, "isFinite", Std_isFinite, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26398 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26399 | v7_def(v7, v7->vals.global_object, "Infinity", 8, attr_internal, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26400 | v7_mk_number(v7, INFINITY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26401 | v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26402 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26403 | init_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26404 | init_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26405 | init_error(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26406 | init_boolean(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26407 | #if V7_ENABLE__Math |
Marko Mikulicic |
0:c0ecb8bf28eb | 26408 | init_math(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26409 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26410 | init_string(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26411 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 26412 | init_regex(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26413 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26414 | init_number(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26415 | init_json(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26416 | #if V7_ENABLE__Date |
Marko Mikulicic |
0:c0ecb8bf28eb | 26417 | init_date(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26418 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26419 | init_function(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26420 | init_js_stdlib(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26422 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 26423 | init_proxy(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26424 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26425 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26426 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 26427 | #line 1 "v7/src/js_stdlib.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 26428 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26429 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26430 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 26431 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 26432 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26434 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26435 | /* because clang-format would break JS code, e.g. === converted to == = ... */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26436 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26437 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26438 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26439 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26440 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26442 | #define STRINGIFY(x) #x |
Marko Mikulicic |
0:c0ecb8bf28eb | 26443 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26444 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26445 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26446 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26448 | static const char js_array_indexOf[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26449 | Object.defineProperty(Array.prototype, "indexOf", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26450 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26451 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26452 | value: function(a, x) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26453 | var i; var r = -1; var b = +x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26454 | if (!b || b < 0) b = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26455 | for (i in this) if (i >= b && (r < 0 || i < r) && this[i] === a) r = +i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26456 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26457 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26459 | static const char js_array_lastIndexOf[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26460 | Object.defineProperty(Array.prototype, "lastIndexOf", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26461 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26462 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26463 | value: function(a, x) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26464 | var i; var r = -1; var b = +x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26465 | if (isNaN(b) || b < 0 || b >= this.length) b = this.length - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26466 | for (i in this) if (i <= b && (r < 0 || i > r) && this[i] === a) r = +i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26467 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26468 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26470 | #if V7_ENABLE__Array__reduce |
Marko Mikulicic |
0:c0ecb8bf28eb | 26471 | static const char js_array_reduce[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26472 | Object.defineProperty(Array.prototype, "reduce", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26473 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26474 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26475 | value: function(a, b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26476 | var f = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26477 | if (typeof(a) != "function") { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26478 | throw new TypeError(a + " is not a function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26479 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26480 | for (var k in this) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26481 | if (k > this.length) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26482 | if (f == 0 && b === undefined) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26483 | b = this[k]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26484 | f = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26485 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26486 | b = a(b, this[k], k, this); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26488 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26489 | return b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26490 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26491 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26493 | static const char js_array_pop[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26494 | Object.defineProperty(Array.prototype, "pop", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26495 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26496 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26497 | value: function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26498 | var i = this.length - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26499 | return this.splice(i, 1)[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26500 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26502 | static const char js_array_shift[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26503 | Object.defineProperty(Array.prototype, "shift", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26504 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26505 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26506 | value: function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26507 | return this.splice(0, 1)[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26508 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26510 | #if V7_ENABLE__Function__call |
Marko Mikulicic |
0:c0ecb8bf28eb | 26511 | static const char js_function_call[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26512 | Object.defineProperty(Function.prototype, "call", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26513 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26514 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26515 | value: function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26516 | var t = arguments.splice(0, 1)[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26517 | return this.apply(t, arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26518 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26519 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26521 | #if V7_ENABLE__Function__bind |
Marko Mikulicic |
0:c0ecb8bf28eb | 26522 | static const char js_function_bind[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26523 | Object.defineProperty(Function.prototype, "bind", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26524 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26525 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26526 | value: function(t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26527 | var f = this; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26528 | return function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26529 | return f.apply(t, arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26530 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26531 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26532 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26533 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26534 | #if V7_ENABLE__Blob |
Marko Mikulicic |
0:c0ecb8bf28eb | 26535 | static const char js_Blob[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26536 | function Blob(a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26537 | this.a = a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26538 | }); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26539 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26540 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26541 | static const char * const js_functions[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26542 | #if V7_ENABLE__Blob |
Marko Mikulicic |
0:c0ecb8bf28eb | 26543 | js_Blob, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26544 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26545 | #if V7_ENABLE__Function__call |
Marko Mikulicic |
0:c0ecb8bf28eb | 26546 | js_function_call, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26547 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26548 | #if V7_ENABLE__Function__bind |
Marko Mikulicic |
0:c0ecb8bf28eb | 26549 | js_function_bind, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26550 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26551 | #if V7_ENABLE__Array__reduce |
Marko Mikulicic |
0:c0ecb8bf28eb | 26552 | js_array_reduce, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26553 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26554 | js_array_indexOf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26555 | js_array_lastIndexOf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26556 | js_array_pop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26557 | js_array_shift |
Marko Mikulicic |
0:c0ecb8bf28eb | 26558 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26560 | V7_PRIVATE void init_js_stdlib(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26561 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26562 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26563 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26564 | for(i = 0; i < (int) ARRAY_SIZE(js_functions); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26565 | if (v7_exec(v7, js_functions[i], &res) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26566 | fprintf(stderr, "ex: %s:\n", js_functions[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26567 | v7_fprintln(stderr, v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26568 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26569 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26571 | /* TODO(lsm): re-enable in a separate PR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26572 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 26573 | v7_exec(v7, &res, STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26574 | Array.prototype.unshift = function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26575 | var a = new Array(0, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26576 | Array.prototype.push.apply(a, arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26577 | Array.prototype.splice.apply(this, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26578 | return this.length; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26579 | };)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26580 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26581 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26582 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26583 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26584 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26585 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26586 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 26587 | #line 1 "v7/src/slre.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 26588 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26589 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26590 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 26591 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 26592 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26593 | * This software is dual-licensed: you can redistribute it and/or modify |
Marko Mikulicic |
0:c0ecb8bf28eb | 26594 | * it under the terms of the GNU General Public License version 2 as |
Marko Mikulicic |
0:c0ecb8bf28eb | 26595 | * published by the Free Software Foundation. For the terms of this |
Marko Mikulicic |
0:c0ecb8bf28eb | 26596 | * license, see <http://www.gnu.org/licenses/>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26597 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26598 | * You are free to use this software under the terms of the GNU General |
Marko Mikulicic |
0:c0ecb8bf28eb | 26599 | * Public License, but WITHOUT ANY WARRANTY; without even the implied |
Marko Mikulicic |
0:c0ecb8bf28eb | 26600 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26601 | * See the GNU General Public License for more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26602 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26603 | * Alternatively, you can license this software under a commercial |
Marko Mikulicic |
0:c0ecb8bf28eb | 26604 | * license, as set out in <https://www.cesanta.com/license>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26605 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26606 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26607 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26608 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26609 | #include <setjmp.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26610 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26611 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26612 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26614 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26615 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26616 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26618 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26619 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26621 | /* Limitations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26622 | #define SLRE_MAX_RANGES 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 26623 | #define SLRE_MAX_SETS 16 |
Marko Mikulicic |
0:c0ecb8bf28eb | 26624 | #define SLRE_MAX_REP 0xFFFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 26625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26626 | #define SLRE_MALLOC malloc |
Marko Mikulicic |
0:c0ecb8bf28eb | 26627 | #define SLRE_FREE free |
Marko Mikulicic |
0:c0ecb8bf28eb | 26628 | #define SLRE_THROW(e, err_code) longjmp((e)->jmp_buf, (err_code)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26630 | static int hex(int c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26631 | if (c >= '0' && c <= '9') return c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26632 | if (c >= 'a' && c <= 'f') return c - 'a' + 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26633 | if (c >= 'A' && c <= 'F') return c - 'A' + 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26634 | return -SLRE_INVALID_HEX_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26637 | int nextesc(const char **p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26638 | const unsigned char *s = (unsigned char *) (*p)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26639 | switch (*s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26640 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26641 | return -SLRE_UNTERM_ESC_SEQ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26642 | case 'c': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26643 | ++*p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26644 | return *s & 31; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26645 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26646 | return '\b'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26647 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26648 | return '\t'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26649 | case 'n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26650 | return '\n'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26651 | case 'v': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26652 | return '\v'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26653 | case 'f': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26654 | return '\f'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26655 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26656 | return '\r'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26657 | case '\\': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26658 | return '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26659 | case 'u': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26660 | if (isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 26661 | isxdigit(s[4])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26662 | (*p) += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26663 | return hex(s[1]) << 12 | hex(s[2]) << 8 | hex(s[3]) << 4 | hex(s[4]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26664 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26665 | return -SLRE_INVALID_HEX_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26666 | case 'x': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26667 | if (isxdigit(s[1]) && isxdigit(s[2])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26668 | (*p) += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26669 | return (hex(s[1]) << 4) | hex(s[2]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26670 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26671 | return -SLRE_INVALID_HEX_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26672 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26673 | return -SLRE_INVALID_ESC_CHAR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26674 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26675 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26676 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26677 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 26678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26679 | /* Parser Information */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26680 | struct slre_node { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26681 | unsigned char type; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26682 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26683 | Rune c; /* character */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26684 | struct slre_class *cp; /* class pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26685 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26686 | struct slre_node *x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26687 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26688 | struct slre_node *y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26689 | unsigned char n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26690 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26691 | unsigned char ng; /* not greedy flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26692 | unsigned short min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26693 | unsigned short max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26694 | } rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26695 | } y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26696 | } xy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26697 | } par; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26698 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26700 | struct slre_range { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26701 | unsigned short s, e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26702 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26704 | /* character class, each pair of rune's defines a range */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26705 | struct slre_class { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26706 | struct slre_range *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26707 | struct slre_range spans[SLRE_MAX_RANGES]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26708 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26710 | struct slre_instruction { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26711 | unsigned char opcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26712 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26713 | unsigned char n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26714 | Rune c; /* character */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26715 | struct slre_class *cp; /* class pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26716 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26717 | struct slre_instruction *x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26718 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26719 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26720 | unsigned short min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26721 | unsigned short max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26722 | } rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26723 | struct slre_instruction *y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26724 | } y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26725 | } xy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26726 | } par; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26727 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26729 | struct slre_prog { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26730 | struct slre_instruction *start, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26731 | unsigned int num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26732 | int flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26733 | struct slre_class charset[SLRE_MAX_SETS]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26734 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26736 | struct slre_env { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26737 | int is_regex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26738 | const char *src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26739 | const char *src_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26740 | Rune curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26741 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26742 | struct slre_prog *prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26743 | struct slre_node *pstart, *pend; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26745 | struct slre_node *caps[SLRE_MAX_CAPS]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26746 | unsigned int num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26747 | unsigned int sets_num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26749 | int lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26750 | struct slre_class *curr_set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26751 | int min_rep, max_rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26753 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26754 | ::jmp_buf jmp_buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26755 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 26756 | jmp_buf jmp_buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26757 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26758 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26760 | struct slre_thread { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26761 | struct slre_thread *prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26762 | struct slre_instruction *pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26763 | const char *start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26764 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26765 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26767 | enum slre_opcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26768 | I_END = 10, /* Terminate: match found */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26769 | I_ANY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26770 | P_ANY = I_ANY, /* Any character except newline, . */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26771 | I_ANYNL, /* Any character including newline, . */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26772 | I_BOL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26773 | P_BOL = I_BOL, /* Beginning of line, ^ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26774 | I_CH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26775 | P_CH = I_CH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26776 | I_EOL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26777 | P_EOL = I_EOL, /* End of line, $ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26778 | I_EOS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26779 | P_EOS = I_EOS, /* End of string, \0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26780 | I_JUMP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26781 | I_LA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26782 | P_LA = I_LA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26783 | I_LA_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26784 | P_LA_N = I_LA_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26785 | I_LBRA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26786 | P_BRA = I_LBRA, /* Left bracket, ( */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26787 | I_REF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26788 | P_REF = I_REF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26789 | I_REP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26790 | P_REP = I_REP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26791 | I_REP_INI, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26792 | I_RBRA, /* Right bracket, ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26793 | I_SET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26794 | P_SET = I_SET, /* Character set, [] */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26795 | I_SET_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26796 | P_SET_N = I_SET_N, /* Negated character set, [] */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26797 | I_SPLIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26798 | I_WORD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26799 | P_WORD = I_WORD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26800 | I_WORD_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26801 | P_WORD_N = I_WORD_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26802 | P_ALT, /* Alternation, | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26803 | P_CAT, /* Concatentation, implicit operator */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26804 | L_CH = 256, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26805 | L_COUNT, /* {M,N} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26806 | L_EOS, /* End of string, \0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26807 | L_LA, /* "(?=" lookahead */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26808 | L_LA_CAP, /* "(?:" lookahead, capture */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26809 | L_LA_N, /* "(?!" negative lookahead */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26810 | L_REF, /* "\1" back-reference */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26811 | L_CHSET, /* character set */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26812 | L_SET_N, /* negative character set */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26813 | L_WORD, /* "\b" word boundary */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26814 | L_WORD_N /* "\B" non-word boundary */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26815 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26817 | static signed char dec(int c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26818 | if (isdigitrune(c)) return c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26819 | return SLRE_INVALID_DEC_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26820 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26821 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26822 | static unsigned char re_dec_digit(struct slre_env *e, int c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26823 | signed char ret = dec(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26824 | if (ret < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26825 | SLRE_THROW(e, SLRE_INVALID_DEC_DIGIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26826 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26827 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26828 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26830 | static int re_nextc(Rune *r, const char **src, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26831 | *r = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26832 | if (*src >= src_end) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26833 | *src += chartorune(r, *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26834 | if (*r == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26835 | const char *tmp_s = *src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26836 | int i = nextesc(src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26837 | switch (i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26838 | case -SLRE_INVALID_ESC_CHAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26839 | *r = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26840 | *src = tmp_s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26841 | *src += chartorune(r, *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26842 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26843 | case -SLRE_INVALID_HEX_DIGIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26844 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26845 | *r = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26847 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26848 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26849 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26850 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26852 | static int re_nextc_raw(Rune *r, const char **src, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26853 | *r = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26854 | if (*src >= src_end) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26855 | *src += chartorune(r, *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26856 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26857 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26859 | static int re_nextc_env(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26860 | return re_nextc(&e->curr_rune, &e->src, e->src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26861 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26863 | static void re_nchset(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26864 | if (e->sets_num >= nelem(e->prog->charset)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26865 | SLRE_THROW(e, SLRE_TOO_MANY_CHARSETS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26867 | e->curr_set = e->prog->charset + e->sets_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26868 | e->curr_set->end = e->curr_set->spans; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26869 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26871 | static void re_rng2set(struct slre_env *e, Rune start, Rune end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26872 | if (start > end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26873 | SLRE_THROW(e, SLRE_INV_CHARSET_RANGE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26874 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26875 | if (e->curr_set->end + 2 == e->curr_set->spans + nelem(e->curr_set->spans)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26876 | SLRE_THROW(e, SLRE_CHARSET_TOO_LARGE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26878 | e->curr_set->end->s = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26879 | e->curr_set->end->e = end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26880 | e->curr_set->end++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26881 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26882 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26883 | #define re_char2set(e, c) re_rng2set(e, c, c) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26885 | #define re_d_2set(e) re_rng2set(e, '0', '9') |
Marko Mikulicic |
0:c0ecb8bf28eb | 26886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26887 | static void re_D_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26888 | re_rng2set(e, 0, '0' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26889 | re_rng2set(e, '9' + 1, 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26890 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26892 | static void re_s_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26893 | re_char2set(e, 0x9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26894 | re_rng2set(e, 0xA, 0xD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26895 | re_char2set(e, 0x20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26896 | re_char2set(e, 0xA0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26897 | re_rng2set(e, 0x2028, 0x2029); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26898 | re_char2set(e, 0xFEFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26899 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26901 | static void re_S_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26902 | re_rng2set(e, 0, 0x9 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26903 | re_rng2set(e, 0xD + 1, 0x20 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26904 | re_rng2set(e, 0x20 + 1, 0xA0 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26905 | re_rng2set(e, 0xA0 + 1, 0x2028 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26906 | re_rng2set(e, 0x2029 + 1, 0xFEFF - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26907 | re_rng2set(e, 0xFEFF + 1, 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26908 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26910 | static void re_w_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26911 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26912 | re_rng2set(e, 'A', 'Z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26913 | re_char2set(e, '_'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26914 | re_rng2set(e, 'a', 'z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26917 | static void re_W_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26918 | re_rng2set(e, 0, '0' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26919 | re_rng2set(e, '9' + 1, 'A' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26920 | re_rng2set(e, 'Z' + 1, '_' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26921 | re_rng2set(e, '_' + 1, 'a' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26922 | re_rng2set(e, 'z' + 1, 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26923 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26925 | static unsigned char re_endofcount(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26926 | switch (c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26927 | case ',': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26928 | case '}': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26929 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26930 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26931 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26932 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26934 | static void re_ex_num_overfl(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26935 | SLRE_THROW(e, SLRE_NUM_OVERFLOW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26936 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26937 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26938 | static enum slre_opcode re_countrep(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26939 | e->min_rep = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26940 | while (e->src < e->src_end && !re_endofcount(e->curr_rune = *e->src++)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26941 | e->min_rep = e->min_rep * 10 + re_dec_digit(e, e->curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26942 | if (e->min_rep >= SLRE_MAX_REP) re_ex_num_overfl(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26943 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26945 | if (e->curr_rune != ',') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26946 | e->max_rep = e->min_rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26947 | return L_COUNT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26948 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26949 | e->max_rep = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26950 | while (e->src < e->src_end && (e->curr_rune = *e->src++) != '}') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26951 | e->max_rep = e->max_rep * 10 + re_dec_digit(e, e->curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26952 | if (e->max_rep >= SLRE_MAX_REP) re_ex_num_overfl(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26953 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26954 | if (!e->max_rep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26955 | e->max_rep = SLRE_MAX_REP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26956 | return L_COUNT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26957 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26959 | return L_COUNT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26960 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26961 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26962 | static enum slre_opcode re_lexset(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26963 | Rune ch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26964 | unsigned char esc, ch_fl = 0, dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26965 | enum slre_opcode type = L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26967 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26969 | esc = re_nextc_env(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26970 | if (!esc && e->curr_rune == '^') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26971 | type = L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26972 | esc = re_nextc_env(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26973 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26975 | for (; esc || e->curr_rune != ']'; esc = re_nextc_env(e)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26976 | if (!e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26977 | SLRE_THROW(e, SLRE_MALFORMED_CHARSET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26978 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26979 | if (esc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26980 | if (strchr("DdSsWw", e->curr_rune)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26981 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26982 | re_char2set(e, ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26983 | if (dash_fl) re_char2set(e, '-'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26984 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26985 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26986 | case 'D': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26987 | re_D_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26988 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26989 | case 'd': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26990 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26991 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26992 | case 'S': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26993 | re_S_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26994 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26995 | case 's': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26996 | re_s_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26997 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26998 | case 'W': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26999 | re_W_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27000 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27001 | case 'w': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27002 | re_w_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27003 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27004 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27005 | ch_fl = dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27006 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27008 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27009 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27010 | /* case '-': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27011 | case '\\': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27012 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27013 | case '/': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27014 | case ']': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27015 | case '|': */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27016 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27017 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27018 | e->curr_rune = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27019 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27020 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27021 | e->curr_rune = '\b'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27022 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27023 | /* default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27024 | SLRE_THROW(e->catch_point, e->err_msg, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27025 | SLRE_INVALID_ESC_CHAR); */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27027 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27028 | if (e->curr_rune == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27029 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27030 | if (dash_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27031 | re_rng2set(e, ch, '-'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27032 | ch_fl = dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27033 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 27034 | dash_fl = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27035 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27036 | ch = '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27037 | ch_fl = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27038 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27039 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27040 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27041 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27042 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27043 | if (dash_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27044 | re_rng2set(e, ch, e->curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27045 | ch_fl = dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27046 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27047 | re_char2set(e, ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27048 | ch = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27049 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27050 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27051 | ch = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27052 | ch_fl = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27053 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27054 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27055 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27056 | re_char2set(e, ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27057 | if (dash_fl) re_char2set(e, '-'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27059 | return type; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27061 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27062 | static int re_lexer(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27063 | if (re_nextc_env(e)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27064 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27065 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27066 | e->curr_rune = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27067 | return L_EOS; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27068 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27069 | return L_WORD; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27070 | case 'B': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27071 | return L_WORD_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27072 | case 'd': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27073 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27074 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27075 | return L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27076 | case 'D': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27077 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27078 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27079 | return L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27080 | case 's': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27081 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27082 | re_s_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27083 | return L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27084 | case 'S': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27085 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27086 | re_s_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27087 | return L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27088 | case 'w': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27089 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27090 | re_w_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27091 | return L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27092 | case 'W': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27093 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27094 | re_w_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27095 | return L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27096 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27097 | if (isdigitrune(e->curr_rune)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27098 | e->curr_rune -= '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27099 | if (isdigitrune(*e->src)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27100 | e->curr_rune = e->curr_rune * 10 + *e->src++ - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27101 | return L_REF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27102 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27103 | return L_CH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27104 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27106 | if (e->is_regex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27107 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27108 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27109 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27110 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27111 | case ')': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27112 | case '*': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27113 | case '+': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27114 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27115 | case '?': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27116 | case '^': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27117 | case '|': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27118 | return e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27119 | case '{': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27120 | return re_countrep(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27121 | case '[': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27122 | return re_lexset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27123 | case '(': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27124 | if (e->src[0] == '?') switch (e->src[1]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27125 | case '=': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27126 | e->src += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27127 | return L_LA; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27128 | case ':': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27129 | e->src += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27130 | return L_LA_CAP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27131 | case '!': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27132 | e->src += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27133 | return L_LA_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27134 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27135 | return '('; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27136 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27137 | } else if (e->curr_rune == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27138 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27139 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27141 | return L_CH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27142 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27144 | #define RE_NEXT(env) (env)->lookahead = re_lexer(env) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27145 | #define RE_ACCEPT(env, t) ((env)->lookahead == (t) ? RE_NEXT(env), 1 : 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27147 | static struct slre_node *re_nnode(struct slre_env *e, int type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27148 | memset(e->pend, 0, sizeof(struct slre_node)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27149 | e->pend->type = type; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27150 | return e->pend++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27151 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27153 | static unsigned char re_isemptynd(struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27154 | if (!nd) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27155 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27156 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27157 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27158 | case P_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27159 | case P_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27160 | case P_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27161 | case P_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27162 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27163 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27164 | case P_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27165 | return re_isemptynd(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27166 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27167 | return re_isemptynd(nd->par.xy.x) && re_isemptynd(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27168 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27169 | return re_isemptynd(nd->par.xy.x) || re_isemptynd(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27170 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27171 | return re_isemptynd(nd->par.xy.x) || !nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27172 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27175 | static struct slre_node *re_nrep(struct slre_env *e, struct slre_node *nd, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27176 | int ng, unsigned short min, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27177 | unsigned short max) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27178 | struct slre_node *rep = re_nnode(e, P_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27179 | if (max == SLRE_MAX_REP && re_isemptynd(nd)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27180 | SLRE_THROW(e, SLRE_INF_LOOP_M_EMP_STR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27181 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27182 | rep->par.xy.y.rp.ng = ng; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27183 | rep->par.xy.y.rp.min = min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27184 | rep->par.xy.y.rp.max = max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27185 | rep->par.xy.x = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27186 | return rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27187 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27189 | static struct slre_node *re_parser(struct slre_env *e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27191 | static struct slre_node *re_parse_la(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27192 | struct slre_node *nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27193 | int min, max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27194 | switch (e->lookahead) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27195 | case '^': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27196 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27197 | return re_nnode(e, P_BOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27198 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27199 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27200 | return re_nnode(e, P_EOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27201 | case L_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27202 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27203 | return re_nnode(e, P_EOS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27204 | case L_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27205 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27206 | return re_nnode(e, P_WORD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27207 | case L_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27208 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27209 | return re_nnode(e, P_WORD_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27210 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27212 | switch (e->lookahead) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27213 | case L_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27214 | nd = re_nnode(e, P_CH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27215 | nd->par.c = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27216 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27217 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27218 | case L_CHSET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27219 | nd = re_nnode(e, P_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27220 | nd->par.cp = e->curr_set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27221 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27222 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27223 | case L_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27224 | nd = re_nnode(e, P_SET_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27225 | nd->par.cp = e->curr_set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27226 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27227 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27228 | case L_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27229 | nd = re_nnode(e, P_REF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27230 | if (!e->curr_rune || e->curr_rune > e->num_captures || |
Marko Mikulicic |
0:c0ecb8bf28eb | 27231 | !e->caps[e->curr_rune]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27232 | SLRE_THROW(e, SLRE_INVALID_BACK_REFERENCE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27233 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27234 | nd->par.xy.y.n = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27235 | nd->par.xy.x = e->caps[e->curr_rune]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27236 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27237 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27238 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27239 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27240 | nd = re_nnode(e, P_ANY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27241 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27242 | case '(': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27243 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27244 | nd = re_nnode(e, P_BRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27245 | if (e->num_captures == SLRE_MAX_CAPS) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27246 | SLRE_THROW(e, SLRE_TOO_MANY_CAPTURES); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27247 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27248 | nd->par.xy.y.n = e->num_captures++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27249 | nd->par.xy.x = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27250 | e->caps[nd->par.xy.y.n] = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27251 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27252 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27253 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27254 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27255 | case L_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27256 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27257 | nd = re_nnode(e, P_LA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27258 | nd->par.xy.x = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27259 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27260 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27261 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27262 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27263 | case L_LA_CAP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27264 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27265 | nd = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27266 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27267 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27268 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27269 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27270 | case L_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27271 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27272 | nd = re_nnode(e, P_LA_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27273 | nd->par.xy.x = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27274 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27275 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27276 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27277 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27278 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27279 | SLRE_THROW(e, SLRE_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27280 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27282 | switch (e->lookahead) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27283 | case '*': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27284 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27285 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, SLRE_MAX_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27286 | case '+': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27287 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27288 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), 1, SLRE_MAX_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27289 | case '?': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27290 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27291 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27292 | case L_COUNT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27293 | min = e->min_rep, max = e->max_rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27294 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27295 | if (max < min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27296 | SLRE_THROW(e, SLRE_INVALID_QUANTIFIER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27297 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27298 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), min, max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27299 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27300 | return nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27303 | static unsigned char re_endofcat(Rune c, int is_regex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27304 | switch (c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27305 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27306 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27307 | case '|': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27308 | case ')': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27309 | if (is_regex) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27310 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27311 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27314 | static struct slre_node *re_parser(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27315 | struct slre_node *alt = NULL, *cat, *nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27316 | if (!re_endofcat(e->lookahead, e->is_regex)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27317 | cat = re_parse_la(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27318 | while (!re_endofcat(e->lookahead, e->is_regex)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27319 | nd = cat; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27320 | cat = re_nnode(e, P_CAT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27321 | cat->par.xy.x = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27322 | cat->par.xy.y.y = re_parse_la(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27323 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27324 | alt = cat; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27325 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27326 | if (e->lookahead == '|') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27327 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27328 | nd = alt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27329 | alt = re_nnode(e, P_ALT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27330 | alt->par.xy.x = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27331 | alt->par.xy.y.y = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27332 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27333 | return alt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27336 | static unsigned int re_nodelen(struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27337 | unsigned int n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27338 | if (!nd) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27339 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27340 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27341 | n = 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27342 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27343 | return re_nodelen(nd->par.xy.x) + re_nodelen(nd->par.xy.y.y) + n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27344 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27345 | case P_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27346 | case P_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27347 | return re_nodelen(nd->par.xy.x) + 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27348 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27349 | n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27350 | switch (nd->par.xy.y.rp.min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27351 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27352 | if (!n) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27353 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27354 | return re_nodelen(nd->par.xy.x) + 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27355 | case 1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27356 | if (!n) return re_nodelen(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27357 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27358 | return re_nodelen(nd->par.xy.x) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27359 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27360 | n = 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27361 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) n++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27362 | return re_nodelen(nd->par.xy.x) + n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27364 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27365 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27366 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27367 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27369 | static struct slre_instruction *re_newinst(struct slre_prog *prog, int opcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27370 | memset(prog->end, 0, sizeof(struct slre_instruction)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27371 | prog->end->opcode = opcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27372 | return prog->end++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27373 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27375 | static void re_compile(struct slre_env *e, struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27376 | struct slre_instruction *inst, *split, *jump, *rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27377 | unsigned int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27379 | if (!nd) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27381 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27382 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27383 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27384 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27385 | jump = re_newinst(e->prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27386 | re_compile(e, nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27387 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27388 | split->par.xy.y.y = jump + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27389 | jump->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27390 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27391 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27392 | case P_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27393 | re_newinst(e->prog, I_ANY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27394 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27396 | case P_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27397 | re_newinst(e->prog, I_BOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27398 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27400 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27401 | inst = re_newinst(e->prog, I_LBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27402 | inst->par.n = nd->par.xy.y.n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27403 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27404 | inst = re_newinst(e->prog, I_RBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27405 | inst->par.n = nd->par.xy.y.n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27406 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27408 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27409 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27410 | re_compile(e, nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27411 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27413 | case P_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27414 | inst = re_newinst(e->prog, I_CH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27415 | inst->par.c = nd->par.c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27416 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27417 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27418 | case P_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27419 | re_newinst(e->prog, I_EOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27420 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27422 | case P_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27423 | re_newinst(e->prog, I_EOS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27424 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27426 | case P_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27427 | split = re_newinst(e->prog, I_LA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27428 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27429 | re_newinst(e->prog, I_END); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27430 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27431 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27432 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27433 | case P_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27434 | split = re_newinst(e->prog, I_LA_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27435 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27436 | re_newinst(e->prog, I_END); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27437 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27438 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27439 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27441 | case P_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27442 | inst = re_newinst(e->prog, I_REF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27443 | inst->par.n = nd->par.xy.y.n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27444 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27446 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27447 | n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27448 | switch (nd->par.xy.y.rp.min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27449 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27450 | if (!n) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27451 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27452 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27453 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27454 | jump = re_newinst(e->prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27455 | jump->par.xy.x = split; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27456 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27457 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27458 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27459 | split->par.xy.y.y = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27460 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27462 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27463 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27464 | case 1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27465 | if (!n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27466 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27467 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27468 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27469 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27470 | inst = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27471 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27472 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27473 | split->par.xy.x = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27474 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27475 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27476 | split->par.xy.y.y = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27477 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27478 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27479 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27481 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27482 | inst = re_newinst(e->prog, I_REP_INI); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27483 | inst->par.xy.y.rp.min = nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27484 | inst->par.xy.y.rp.max = n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27485 | rep = re_newinst(e->prog, I_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27486 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27487 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27488 | jump = re_newinst(e->prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27489 | jump->par.xy.x = rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27490 | rep->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27491 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27492 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27493 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27494 | split->par.xy.y.y = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27495 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27497 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27498 | inst = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27499 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27500 | split->par.xy.x = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27501 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27502 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27503 | split->par.xy.y.y = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27504 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27505 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27506 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27507 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27508 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27509 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27510 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27512 | case P_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27513 | inst = re_newinst(e->prog, I_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27514 | inst->par.cp = nd->par.cp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27515 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27516 | case P_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27517 | inst = re_newinst(e->prog, I_SET_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27518 | inst->par.cp = nd->par.cp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27519 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27521 | case P_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27522 | re_newinst(e->prog, I_WORD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27523 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27524 | case P_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27525 | re_newinst(e->prog, I_WORD_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27526 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27527 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27528 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27529 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27530 | #ifdef RE_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 27531 | static void print_set(struct slre_class *cp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27532 | struct slre_range *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27533 | for (p = cp->spans; p < cp->end; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27534 | printf("%s", p == cp->spans ? "'" : ",'"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27535 | printf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 27536 | p->s >= 32 && p->s < 127 ? "%c" : (p->s < 256 ? "\\x%02X" : "\\u%04X"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 27537 | p->s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27538 | if (p->s != p->e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27539 | printf(p->e >= 32 && p->e < 127 ? "-%c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 27540 | : (p->e < 256 ? "-\\x%02X" : "-\\u%04X"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 27541 | p->e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27543 | printf("'"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27544 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27545 | printf("]"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27546 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27548 | static void node_print(struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27549 | if (!nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27550 | printf("Empty"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27551 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27552 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27553 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27554 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27555 | printf("{"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27556 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27557 | printf(" | "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27558 | node_print(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27559 | printf("}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27560 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27561 | case P_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27562 | printf("."); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27563 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27564 | case P_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27565 | printf("^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27566 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27567 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27568 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27569 | printf(")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27570 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27571 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27572 | printf("{"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27573 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27574 | printf(" & "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27575 | node_print(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27576 | printf("}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27577 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27578 | case P_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27579 | printf(nd->par.c >= 32 && nd->par.c < 127 ? "'%c'" : "'\\u%04X'", |
Marko Mikulicic |
0:c0ecb8bf28eb | 27580 | nd->par.c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27581 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27582 | case P_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27583 | printf("$"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27584 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27585 | case P_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27586 | printf("\\0"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27587 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27588 | case P_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27589 | printf("LA("); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27590 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27591 | printf(")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27592 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27593 | case P_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27594 | printf("LA_N("); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27595 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27596 | printf(")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27597 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27598 | case P_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27599 | printf("\\%d", nd->par.xy.y.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27600 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27601 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27602 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27603 | printf(nd->par.xy.y.rp.ng ? "{%d,%d}?" : "{%d,%d}", nd->par.xy.y.rp.min, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27604 | nd->par.xy.y.rp.max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27605 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27606 | case P_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27607 | printf("["); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27608 | print_set(nd->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27609 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27610 | case P_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27611 | printf("[^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27612 | print_set(nd->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27613 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27614 | case P_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27615 | printf("\\b"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27616 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27617 | case P_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27618 | printf("\\B"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27619 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27620 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27621 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27623 | static void program_print(struct slre_prog *prog) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27624 | struct slre_instruction *inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27625 | for (inst = prog->start; inst < prog->end; ++inst) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27626 | printf("%3d: ", inst - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27627 | switch (inst->opcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27628 | case I_END: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27629 | puts("end"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27630 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27631 | case I_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27632 | puts("."); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27633 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27634 | case I_ANYNL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27635 | puts(". | '\\r' | '\\n'"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27636 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27637 | case I_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27638 | puts("^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27639 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27640 | case I_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27641 | printf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 27642 | inst->par.c >= 32 && inst->par.c < 127 ? "'%c'\n" : "'\\u%04X'\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 27643 | inst->par.c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27644 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27645 | case I_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27646 | puts("$"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27647 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27648 | case I_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27649 | puts("\\0"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27650 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27651 | case I_JUMP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27652 | printf("-->%d\n", inst->par.xy.x - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27653 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27654 | case I_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27655 | printf("la %d %d\n", inst->par.xy.x - prog->start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27656 | inst->par.xy.y.y - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27657 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27658 | case I_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27659 | printf("la_n %d %d\n", inst->par.xy.x - prog->start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27660 | inst->par.xy.y.y - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27661 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27662 | case I_LBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27663 | printf("( %d\n", inst->par.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27664 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27665 | case I_RBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27666 | printf(") %d\n", inst->par.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27667 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27668 | case I_SPLIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27669 | printf("-->%d | -->%d\n", inst->par.xy.x - prog->start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27670 | inst->par.xy.y.y - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27671 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27672 | case I_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27673 | printf("\\%d\n", inst->par.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27674 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27675 | case I_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27676 | printf("repeat -->%d\n", inst->par.xy.x - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27677 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27678 | case I_REP_INI: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27679 | printf("init_rep %d %d\n", inst->par.xy.y.rp.min, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27680 | inst->par.xy.y.rp.min + inst->par.xy.y.rp.max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27681 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27682 | case I_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27683 | printf("["); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27684 | print_set(inst->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27685 | puts(""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27686 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27687 | case I_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27688 | printf("[^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27689 | print_set(inst->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27690 | puts(""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27691 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27692 | case I_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27693 | puts("\\w"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27694 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27695 | case I_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27696 | puts("\\W"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27697 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27698 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27700 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27701 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 27702 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27703 | int slre_compile(const char *pat, size_t pat_len, const char *flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27704 | volatile size_t fl_len, struct slre_prog **pr, int is_regex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27705 | struct slre_env e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27706 | struct slre_node *nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27707 | struct slre_instruction *split, *jump; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27708 | int err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27710 | e.is_regex = is_regex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27711 | e.prog = (struct slre_prog *) SLRE_MALLOC(sizeof(struct slre_prog)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27712 | e.pstart = e.pend = |
Marko Mikulicic |
0:c0ecb8bf28eb | 27713 | (struct slre_node *) SLRE_MALLOC(sizeof(struct slre_node) * pat_len * 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27714 | e.prog->flags = is_regex ? SLRE_FLAG_RE : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27716 | if ((err_code = setjmp(e.jmp_buf)) != SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27717 | SLRE_FREE(e.pstart); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27718 | SLRE_FREE(e.prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27719 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27720 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27722 | while (fl_len--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27723 | switch (flags[fl_len]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27724 | case 'g': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27725 | e.prog->flags |= SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27726 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27727 | case 'i': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27728 | e.prog->flags |= SLRE_FLAG_I; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27729 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27730 | case 'm': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27731 | e.prog->flags |= SLRE_FLAG_M; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27732 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27733 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27734 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27736 | e.src = pat; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27737 | e.src_end = pat + pat_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27738 | e.sets_num = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27739 | e.num_captures = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27740 | /*e.flags = flags;*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27741 | memset(e.caps, 0, sizeof(e.caps)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27743 | RE_NEXT(&e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27744 | nd = re_parser(&e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27745 | if (e.lookahead == ')') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27746 | SLRE_THROW(&e, SLRE_UNMATCH_RBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27747 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27748 | if (e.lookahead != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27749 | SLRE_THROW(&e, SLRE_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27750 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27751 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27752 | e.prog->num_captures = e.num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27753 | e.prog->start = e.prog->end = (struct slre_instruction *) SLRE_MALLOC( |
Marko Mikulicic |
0:c0ecb8bf28eb | 27754 | (re_nodelen(nd) + 6) * sizeof(struct slre_instruction)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27756 | split = re_newinst(e.prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27757 | split->par.xy.x = split + 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27758 | split->par.xy.y.y = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27759 | re_newinst(e.prog, I_ANYNL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27760 | jump = re_newinst(e.prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27761 | jump->par.xy.x = split; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27762 | re_newinst(e.prog, I_LBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27763 | re_compile(&e, nd); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27764 | re_newinst(e.prog, I_RBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27765 | re_newinst(e.prog, I_END); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27767 | #ifdef RE_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 27768 | node_print(nd); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27769 | putchar('\n'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27770 | program_print(e.prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27771 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 27772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27773 | SLRE_FREE(e.pstart); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27775 | if (pr != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27776 | *pr = e.prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27777 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27778 | slre_free(e.prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27779 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27780 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27781 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27782 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27784 | void slre_free(struct slre_prog *prog) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27785 | if (prog) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27786 | SLRE_FREE(prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27787 | SLRE_FREE(prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27788 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27789 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27790 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27791 | static struct slre_thread *re_newthread(struct slre_thread *t, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27792 | struct slre_instruction *pc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27793 | const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27794 | struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27795 | struct slre_thread *new_thread = |
Marko Mikulicic |
0:c0ecb8bf28eb | 27796 | (struct slre_thread *) SLRE_MALLOC(sizeof(struct slre_thread)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27797 | if (new_thread != NULL) new_thread->prev = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27798 | t->pc = pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27799 | t->start = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27800 | t->loot = *loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27801 | return new_thread; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27804 | static struct slre_thread *get_prev_thread(struct slre_thread *t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27805 | struct slre_thread *tmp_thr = t->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27806 | SLRE_FREE(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27807 | return tmp_thr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27808 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27810 | static void free_threads(struct slre_thread *t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27811 | while (t->prev != NULL) t = get_prev_thread(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27812 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27813 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27814 | static unsigned char re_match(struct slre_instruction *pc, const char *current, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27815 | const char *end, const char *bol, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27816 | unsigned int flags, struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27817 | struct slre_loot sub, tmpsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27818 | Rune c, r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27819 | struct slre_range *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27820 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27821 | struct slre_thread thread, *curr_thread, *tmp_thr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27823 | /* queue initial thread */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27824 | thread.prev = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27825 | curr_thread = re_newthread(&thread, pc, current, loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27827 | /* run threads in stack order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27828 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27829 | curr_thread = get_prev_thread(curr_thread); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27830 | pc = curr_thread->pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27831 | current = curr_thread->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27832 | sub = curr_thread->loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27833 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27834 | switch (pc->opcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27835 | case I_END: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27836 | memcpy(loot->caps, sub.caps, sizeof loot->caps); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27837 | free_threads(curr_thread); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27838 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27839 | case I_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27840 | case I_ANYNL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27841 | if (current < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27842 | current += chartorune(&c, current); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27843 | if (c && !(pc->opcode == I_ANY && isnewline(c))) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27845 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27846 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27847 | case I_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27848 | if (current == bol) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27849 | if ((flags & SLRE_FLAG_M) && isnewline(current[-1])) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27850 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27851 | case I_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27852 | if (current < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27853 | current += chartorune(&c, current); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27854 | if (c && |
Marko Mikulicic |
0:c0ecb8bf28eb | 27855 | (c == pc->par.c || ((flags & SLRE_FLAG_I) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 27856 | tolowerrune(c) == tolowerrune(pc->par.c)))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27857 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27859 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27860 | case I_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27861 | if (current >= end) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27862 | if ((flags & SLRE_FLAG_M) && isnewline(*current)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27863 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27864 | case I_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27865 | if (current >= end) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27866 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27868 | case I_JUMP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27869 | pc = pc->par.xy.x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27870 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27872 | case I_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27873 | if (re_match(pc->par.xy.x, current, end, bol, flags, &sub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27874 | pc = pc->par.xy.y.y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27875 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27876 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27877 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27878 | case I_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27879 | tmpsub = sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27880 | if (!re_match(pc->par.xy.x, current, end, bol, flags, &tmpsub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27881 | pc = pc->par.xy.y.y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27882 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27883 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27884 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27886 | case I_LBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27887 | sub.caps[pc->par.n].start = current; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27888 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27890 | case I_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27891 | i = sub.caps[pc->par.n].end - sub.caps[pc->par.n].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27892 | if (flags & SLRE_FLAG_I) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27893 | int num = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27894 | const char *s = current, *p = sub.caps[pc->par.n].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27895 | Rune rr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27896 | for (; num && *s && *p; num--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27897 | s += chartorune(&r, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27898 | p += chartorune(&rr, p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27899 | if (tolowerrune(r) != tolowerrune(rr)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27900 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27901 | if (num) goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27902 | } else if (strncmp(current, sub.caps[pc->par.n].start, i)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27903 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27904 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27905 | if (i > 0) current += i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27906 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27907 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27908 | case I_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27909 | if (pc->par.xy.y.rp.min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27910 | pc->par.xy.y.rp.min--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27911 | pc++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27912 | } else if (!pc->par.xy.y.rp.max--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27913 | pc = pc->par.xy.x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27914 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27916 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27918 | case I_REP_INI: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27919 | (pc + 1)->par.xy.y.rp.min = pc->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27920 | (pc + 1)->par.xy.y.rp.max = pc->par.xy.y.rp.max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27921 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27923 | case I_RBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27924 | sub.caps[pc->par.n].end = current; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27925 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27927 | case I_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27928 | case I_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27929 | if (current >= end) goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27930 | current += chartorune(&c, current); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27931 | if (!c) goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27933 | i = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27934 | for (p = pc->par.cp->spans; i && p < pc->par.cp->end; p++) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27935 | if (flags & SLRE_FLAG_I) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27936 | for (r = p->s; r <= p->e; ++r) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27937 | if (tolowerrune(c) == tolowerrune(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27938 | i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27939 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27940 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27941 | } else if (p->s <= c && c <= p->e) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27942 | i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27944 | if (pc->opcode == I_SET) i = !i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27945 | if (i) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27946 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27948 | case I_SPLIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27949 | tmp_thr = curr_thread; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27950 | curr_thread = |
Marko Mikulicic |
0:c0ecb8bf28eb | 27951 | re_newthread(curr_thread, pc->par.xy.y.y, current, &sub); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27952 | if (curr_thread == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27953 | fprintf(stderr, "re_match: no memory for thread!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27954 | free_threads(tmp_thr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27955 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27956 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27957 | pc = pc->par.xy.x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27958 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27960 | case I_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27961 | case I_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27962 | i = (current > bol && iswordchar(current[-1])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27963 | if (iswordchar(current[0])) i = !i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27964 | if (pc->opcode == I_WORD_N) i = !i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27965 | if (i) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27966 | /* goto no_match; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27968 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27969 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27970 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27971 | pc++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27973 | no_match: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27974 | ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27975 | } while (curr_thread->prev != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27976 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27977 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27979 | int slre_exec(struct slre_prog *prog, int flag_g, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27980 | const char *end, struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27981 | struct slre_loot tmpsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27982 | const char *st = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27984 | if (!loot) loot = &tmpsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27985 | memset(loot, 0, sizeof(*loot)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27987 | if (!flag_g) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27988 | loot->num_captures = prog->num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27989 | return !re_match(prog->start, start, end, start, prog->flags, loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27990 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27991 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27992 | while (re_match(prog->start, st, end, start, prog->flags, &tmpsub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27993 | unsigned int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27994 | st = tmpsub.caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27995 | for (i = 0; i < prog->num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27996 | struct slre_cap *l = &loot->caps[loot->num_captures + i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27997 | struct slre_cap *s = &tmpsub.caps[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27998 | l->start = s->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27999 | l->end = s->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28001 | loot->num_captures += prog->num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28002 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28003 | return !loot->num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28004 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28005 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28006 | int slre_replace(struct slre_loot *loot, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28007 | const char *rstr, size_t rstr_len, struct slre_loot *dstsub) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28008 | int size = 0, n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28009 | Rune curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28010 | const char *const rstr_end = rstr + rstr_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28012 | memset(dstsub, 0, sizeof(*dstsub)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28013 | while (rstr < rstr_end && !(n = re_nextc_raw(&curr_rune, &rstr, rstr_end)) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 28014 | curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28015 | int sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28016 | if (n < 0) return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28017 | if (curr_rune == '$') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28018 | n = re_nextc(&curr_rune, &rstr, rstr_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28019 | if (n < 0) return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28020 | switch (curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28021 | case '&': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28022 | sz = loot->caps[0].end - loot->caps[0].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28023 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28024 | dstsub->caps[dstsub->num_captures++] = loot->caps[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28025 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28026 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28027 | case '1': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28028 | case '2': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28029 | case '3': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28030 | case '4': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28031 | case '5': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28032 | case '6': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28033 | case '7': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28034 | case '8': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28035 | case '9': { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28036 | int sbn = dec(curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28037 | if (0 == sbn && rstr[0] && isdigitrune(rstr[0])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28038 | n = re_nextc(&curr_rune, &rstr, rstr_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28039 | if (n < 0) return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28040 | sz = dec(curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28041 | sbn = sbn * 10 + sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28042 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28043 | if (sbn >= loot->num_captures) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28044 | sz = loot->caps[sbn].end - loot->caps[sbn].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28045 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28046 | dstsub->caps[dstsub->num_captures++] = loot->caps[sbn]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28047 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28049 | case '`': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28050 | sz = loot->caps[0].start - src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28051 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28052 | dstsub->caps[dstsub->num_captures].start = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28053 | dstsub->caps[dstsub->num_captures++].end = loot->caps[0].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28054 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28055 | case '\'': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28056 | sz = src + src_len - loot->caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28057 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28058 | dstsub->caps[dstsub->num_captures].start = loot->caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28059 | dstsub->caps[dstsub->num_captures++].end = loot->caps[0].end + sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28060 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28061 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28062 | size++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28063 | dstsub->caps[dstsub->num_captures].start = rstr - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28064 | dstsub->caps[dstsub->num_captures++].end = rstr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28065 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28066 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28067 | return SLRE_BAD_CHAR_AFTER_USD; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28068 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28069 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28070 | char tmps[300], *d = tmps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28071 | size += (sz = runetochar(d, &curr_rune)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28072 | if (!dstsub->num_captures || |
Marko Mikulicic |
0:c0ecb8bf28eb | 28073 | dstsub->caps[dstsub->num_captures - 1].end != rstr - sz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28074 | dstsub->caps[dstsub->num_captures].start = rstr - sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28075 | dstsub->caps[dstsub->num_captures++].end = rstr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28076 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 28077 | dstsub->caps[dstsub->num_captures - 1].end = rstr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28078 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28079 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28080 | return size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28083 | int slre_match(const char *re, size_t re_len, const char *flags, size_t fl_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28084 | const char *str, size_t str_len, struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28085 | struct slre_prog *prog = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28086 | int res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28087 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28088 | if ((res = slre_compile(re, re_len, flags, fl_len, &prog, 1)) == SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28089 | res = slre_exec(prog, prog->flags & SLRE_FLAG_G, str, str + str_len, loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28090 | slre_free(prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28091 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28092 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28093 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28094 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28095 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28096 | int slre_get_flags(struct slre_prog *crp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28097 | return crp->flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28098 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28099 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28100 | #ifdef SLRE_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 28101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28102 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28104 | static const char *err_code_to_str(int err_code) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28105 | static const char *ar[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28106 | "no error", "invalid decimal digit", "invalid hex digit", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28107 | "invalid escape character", "invalid unterminated escape sequence", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28108 | "syntax error", "unmatched left parenthesis", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28109 | "unmatched right parenthesis", "numeric overflow", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28110 | "infinite loop empty string", "too many charsets", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28111 | "invalid charset range", "charset is too large", "malformed charset", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28112 | "invalid back reference", "too many captures", "invalid quantifier", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28113 | "bad character after $"}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28115 | typedef char static_assertion_err_codes_out_of_sync |
Marko Mikulicic |
0:c0ecb8bf28eb | 28116 | [2 * !!(((sizeof(ar) / sizeof(ar[0])) == SLRE_BAD_CHAR_AFTER_USD + 1)) - |
Marko Mikulicic |
0:c0ecb8bf28eb | 28117 | 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28118 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28119 | return err_code >= 0 && err_code < (int) (sizeof(ar) / sizeof(ar[0])) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28120 | ? ar[err_code] |
Marko Mikulicic |
0:c0ecb8bf28eb | 28121 | : "invalid error code"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28122 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28123 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28124 | #define RE_TEST_STR_SIZE 2000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28125 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28126 | static unsigned get_flags(const char *ch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28127 | unsigned int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28128 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28129 | while (*ch != '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28130 | switch (*ch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28131 | case 'g': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28132 | flags |= SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28133 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28134 | case 'i': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28135 | flags |= SLRE_FLAG_I; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28136 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28137 | case 'm': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28138 | flags |= SLRE_FLAG_M; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28139 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28140 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28141 | flags |= SLRE_FLAG_RE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28142 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28143 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28144 | return flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28145 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28146 | ch++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28147 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28148 | return flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28149 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28151 | static void show_usage_and_exit(char *argv[]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28152 | fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28153 | fprintf(stderr, "%s\n", "OPTIONS:"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28154 | fprintf(stderr, "%s\n", " -p <regex_pattern> Regex pattern"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28155 | fprintf(stderr, "%s\n", " -o <regex_flags> Combination of g,i,m"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28156 | fprintf(stderr, "%s\n", " -s <string> String to match"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28157 | fprintf(stderr, "%s\n", " -f <file_name> Match lines from file"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28158 | fprintf(stderr, "%s\n", " -n <cap_no> Show given capture"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28159 | fprintf(stderr, "%s\n", " -r <replace_str> Replace given capture"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28160 | fprintf(stderr, "%s\n", " -v Show verbose stats"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28161 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28162 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28164 | static int process_line(struct slre_prog *pr, const char *flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28165 | const char *line, const char *cap_no, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28166 | const char *replace, const char *verbose) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28167 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28168 | unsigned int fl = flags == NULL ? 0 : get_flags(flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28169 | int i, n = cap_no == NULL ? -1 : atoi(cap_no), err_code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28170 | struct slre_cap *cap = &loot.caps[n]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28172 | err_code = |
Marko Mikulicic |
0:c0ecb8bf28eb | 28173 | slre_exec(pr, pr->flags & SLRE_FLAG_G, line, line + strlen(line), &loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28174 | if (err_code == SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28175 | if (n >= 0 && n < loot.num_captures && replace != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28176 | struct slre_cap *cap = &loot.caps[n]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28177 | printf("%.*s", (int) (cap->start - line), line); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28178 | printf("%s", replace); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28179 | printf("%.*s", (int) ((line + strlen(line)) - cap->end), cap->end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28180 | } else if (n >= 0 && n < loot.num_captures) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28181 | printf("%.*s\n", (int) (cap->end - cap->start), cap->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28182 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28183 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28184 | if (verbose != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28185 | fprintf(stderr, "%s\n", "Captures:"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28186 | for (i = 0; i < loot.num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28187 | fprintf(stderr, "%d [%.*s]\n", i, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28188 | (int) (loot.caps[i].end - loot.caps[i].start), |
Marko Mikulicic |
0:c0ecb8bf28eb | 28189 | loot.caps[i].start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28190 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28191 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28194 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28197 | int main(int argc, char **argv) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28198 | const char *str = NULL, *pattern = NULL, *replace = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28199 | const char *flags = "", *file_name = NULL, *cap_no = NULL, *verbose = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28200 | struct slre_prog *pr = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28201 | int i, err_code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28203 | /* Execute inline code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28204 | for (i = 1; i < argc; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28205 | if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28206 | pattern = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28207 | } else if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28208 | flags = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28209 | } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28210 | str = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28211 | } else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28212 | file_name = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28213 | } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28214 | cap_no = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28215 | } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28216 | replace = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28217 | } else if (strcmp(argv[i], "-v") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28218 | verbose = ""; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28219 | } else if (strcmp(argv[i], "-h") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28220 | show_usage_and_exit(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28221 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28222 | show_usage_and_exit(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28223 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28224 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28226 | if (pattern == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28227 | fprintf(stderr, "%s\n", "-p option is mandatory"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28228 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28229 | } else if ((err_code = slre_compile(pattern, strlen(pattern), flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28230 | strlen(flags), &pr, 1)) != SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28231 | fprintf(stderr, "slre_compile(%s): %s\n", argv[0], |
Marko Mikulicic |
0:c0ecb8bf28eb | 28232 | err_code_to_str(err_code)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28233 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28234 | } else if (str != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28235 | err_code = process_line(pr, flags, str, cap_no, replace, verbose); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28236 | } else if (file_name != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28237 | FILE *fp = strcmp(file_name, "-") == 0 ? stdin : fopen(file_name, "rb"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28238 | char line[20 * 1024]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28239 | if (fp == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28240 | fprintf(stderr, "Cannot open %s: %s\n", file_name, strerror(errno)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28241 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28242 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28243 | /* Return success if at least one line matches */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28244 | err_code = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28245 | while (fgets(line, sizeof(line), fp) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28246 | if (process_line(pr, flags, line, cap_no, replace, verbose) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 28247 | SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28248 | err_code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28251 | fclose(fp); /* If fp == stdin, it is safe to close, too */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28252 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28253 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28254 | fprintf(stderr, "%s\n", "Please specify one of -s or -f options"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28255 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28256 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28257 | slre_free(pr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28258 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28259 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28260 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28261 | #endif /* SLRE_TEST */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28263 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28264 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 28265 | #line 1 "v7/src/heapusage.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 28266 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28267 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28268 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 28269 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 28270 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28272 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28273 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28274 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28275 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28276 | #if defined(V7_HEAPUSAGE_ENABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28278 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28279 | * A flag that is set by GC before allocating its buffers, so we can |
Marko Mikulicic |
0:c0ecb8bf28eb | 28280 | * distinguish these buffers from other allocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 28281 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28282 | volatile int heap_dont_count = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28284 | extern void *__real_malloc(size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28285 | extern void *__real_calloc(size_t num, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28286 | extern void *__real_realloc(void *p, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28287 | extern void __real_free(void *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28289 | /* TODO(dfrank): make it dynamically allocated from heap */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28290 | #define CELLS_CNT (1024 * 32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28292 | typedef struct cell { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28293 | void *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28294 | unsigned dont_count : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28295 | unsigned size : 31; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28296 | } cell_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28298 | typedef struct alloc_registry { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28299 | size_t used_cells_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28300 | size_t allocated_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28301 | size_t real_used_cells_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28302 | size_t real_allocated_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28303 | cell_t cells[CELLS_CNT]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28304 | } alloc_registry_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28305 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28306 | static alloc_registry_t registry = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28308 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28309 | * Make a record about an allocated buffer `p` of size `size` |
Marko Mikulicic |
0:c0ecb8bf28eb | 28310 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28311 | static void cell_allocated(void *p, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28312 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28313 | int cell_num = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28315 | if (p != NULL && size != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28316 | /* TODO(dfrank): make it dynamically allocated from heap */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28317 | assert(registry.real_used_cells_cnt < CELLS_CNT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28319 | for (i = 0; i < CELLS_CNT; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28320 | if (registry.cells[i].p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28321 | cell_num = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28322 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28323 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28324 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28325 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28326 | assert(cell_num != -1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28328 | registry.cells[cell_num].p = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28329 | registry.cells[cell_num].size = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28330 | registry.cells[cell_num].dont_count = !!heap_dont_count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28332 | registry.real_allocated_size += size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28333 | registry.real_used_cells_cnt += 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28334 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28335 | if (!heap_dont_count) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28336 | registry.allocated_size += size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28337 | registry.used_cells_cnt += 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28338 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28340 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28341 | printf("alloc=0x%lx, size=%lu, total=%lu\n", (unsigned long)p, size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28342 | registry.allocated_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28343 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28345 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28347 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28348 | * Delete a record about an allocated buffer `p`. If our registry does not |
Marko Mikulicic |
0:c0ecb8bf28eb | 28349 | * contain anything about the given pointer, the call is ignored. We can't |
Marko Mikulicic |
0:c0ecb8bf28eb | 28350 | * generate an error because shared libraries still use unwrapped heap |
Marko Mikulicic |
0:c0ecb8bf28eb | 28351 | * functions, so we can face "unknown" pointers. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28352 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28353 | static void cell_freed(void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28354 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28355 | int cell_num = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28357 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28358 | assert(registry.real_used_cells_cnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28360 | for (i = 0; i < CELLS_CNT; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28361 | if (registry.cells[i].p == p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28362 | cell_num = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28363 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28365 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28366 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28367 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28368 | * NOTE: it would be nice to have `assert(cell_num != -1);`, but |
Marko Mikulicic |
0:c0ecb8bf28eb | 28369 | * unfortunately not all allocations are wrapped: shared libraries will |
Marko Mikulicic |
0:c0ecb8bf28eb | 28370 | * still use unwrapped mallocs, so we might get unknown pointers here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28371 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28373 | if (cell_num != -1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28374 | registry.real_allocated_size -= registry.cells[cell_num].size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28375 | registry.real_used_cells_cnt -= 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28377 | if (!registry.cells[cell_num].dont_count) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28378 | registry.allocated_size -= registry.cells[cell_num].size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28379 | registry.used_cells_cnt -= 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28380 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28381 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28382 | registry.cells[cell_num].p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28383 | registry.cells[cell_num].size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28384 | registry.cells[cell_num].dont_count = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28386 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28387 | printf("free=0x%lx, total=%lu\n", (unsigned long)p, registry.allocated_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28388 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28389 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28390 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28391 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28393 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28394 | * Wrappers of the standard heap functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 28395 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28397 | void *__wrap_malloc(size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28398 | void *ret = __real_malloc(size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28399 | cell_allocated(ret, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28400 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28401 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28402 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28403 | void *__wrap_calloc(size_t num, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28404 | void *ret = __real_calloc(num, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28405 | cell_allocated(ret, num * size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28406 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28409 | void *__wrap_realloc(void *p, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28410 | void *ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28411 | cell_freed(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28412 | ret = __real_realloc(p, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28413 | cell_allocated(ret, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28414 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28415 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28417 | void __wrap_free(void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28418 | __real_free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28419 | cell_freed(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28420 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28422 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28423 | * Small API to get some stats, see header file for details |
Marko Mikulicic |
0:c0ecb8bf28eb | 28424 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28426 | size_t heapusage_alloc_size(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28427 | return registry.allocated_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28428 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28430 | size_t heapusage_allocs_cnt(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28431 | return registry.used_cells_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28432 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28434 | #endif /* V7_HEAPUSAGE_ENABLE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28435 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 28436 | #line 1 "v7/src/cyg_profile.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 28437 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28438 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28439 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 28440 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 28441 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28443 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28444 | * This file contains GCC/clang instrumentation callbacks. The actual |
Marko Mikulicic |
0:c0ecb8bf28eb | 28445 | * code in these callbacks depends on enabled features. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28446 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 28447 | * Currently, the code from different subsystems is embedded right into |
Marko Mikulicic |
0:c0ecb8bf28eb | 28448 | * callbacks for performance reasons. It would be probably more elegant |
Marko Mikulicic |
0:c0ecb8bf28eb | 28449 | * to have subsystem-specific functions that will be called from these |
Marko Mikulicic |
0:c0ecb8bf28eb | 28450 | * callbacks, but since the callbacks are called really a lot (on each v7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28451 | * function call), I decided it's better to inline the code right here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28452 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28453 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28454 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28455 | /* Amalgamated: #include "v7/src/cyg_profile.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28456 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28457 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28458 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28460 | #if defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28462 | #define CALL_TRACE_SIZE 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28464 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28465 | uint16_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28466 | uint16_t missed_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28467 | void *addresses[CALL_TRACE_SIZE]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28468 | } call_trace_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28470 | static call_trace_t call_trace = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28472 | NOINSTR |
Marko Mikulicic |
0:c0ecb8bf28eb | 28473 | void call_trace_print(const char *prefix, const char *suffix, size_t skip_cnt, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28474 | size_t max_cnt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28475 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28476 | if (call_trace.missed_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28477 | fprintf(stderr, "missed calls! (%d) ", (int) call_trace.missed_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28478 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28479 | if (prefix != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28480 | fprintf(stderr, "%s", prefix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28481 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28482 | for (i = (int) call_trace.size - 1 - skip_cnt; i >= 0; i--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28483 | fprintf(stderr, " %lx", (unsigned long) call_trace.addresses[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28484 | if (max_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28485 | if (--max_cnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28486 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28488 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28489 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28490 | if (suffix != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28491 | fprintf(stderr, "%s", suffix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28492 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28493 | fprintf(stderr, "\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28494 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28495 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28496 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28497 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28498 | #ifndef IRAM |
Marko Mikulicic |
0:c0ecb8bf28eb | 28499 | #define IRAM |
Marko Mikulicic |
0:c0ecb8bf28eb | 28500 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28502 | #ifndef NOINSTR |
Marko Mikulicic |
0:c0ecb8bf28eb | 28503 | #define NOINSTR __attribute__((no_instrument_function)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28504 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28506 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28507 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28508 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28509 | IRAM NOINSTR void __cyg_profile_func_enter(void *this_fn, void *call_site); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28511 | IRAM NOINSTR void __cyg_profile_func_exit(void *this_fn, void *call_site); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28513 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28514 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28515 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28517 | IRAM void __cyg_profile_func_enter(void *this_fn, void *call_site) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28518 | #if defined(V7_STACK_GUARD_MIN_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28519 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28520 | static int profile_enter = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28521 | void *fp = __builtin_frame_address(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28523 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28525 | if (profile_enter || v7_sp_limit == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28527 | profile_enter++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28528 | if (v7_head != NULL && fp < v7_head->sp_lwm) v7_head->sp_lwm = fp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28529 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28530 | if (((int) fp - (int) v7_sp_limit) < V7_STACK_GUARD_MIN_SIZE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28531 | printf("fun %p sp %p limit %p left %d\n", this_fn, fp, v7_sp_limit, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28532 | (int) fp - (int) v7_sp_limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28533 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28534 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28535 | profile_enter--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28536 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28537 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28538 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28539 | #if defined(V7_ENABLE_GC_CHECK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28540 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28541 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28542 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28544 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28546 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28547 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28548 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28549 | struct stack_track_ctx *ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28550 | void *fp = __builtin_frame_address(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28552 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28553 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28555 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28556 | * TODO(dfrank): it actually won't work for multiple instances of v7 running |
Marko Mikulicic |
0:c0ecb8bf28eb | 28557 | * in parallel threads. We need to know the exact v7 instance for which |
Marko Mikulicic |
0:c0ecb8bf28eb | 28558 | * current function is called, but so far I failed to find a way to do this. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28559 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28560 | for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28561 | for (ctx = v7->stack_track_ctx; ctx != NULL; ctx = ctx->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28562 | /* commented because it fails on legal code compiled with -O3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28563 | /*assert(fp <= ctx->start);*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28565 | if (fp < ctx->max) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28566 | ctx->max = fp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28567 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28568 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28569 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28570 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28571 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28573 | #if defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28574 | if (call_trace.size < CALL_TRACE_SIZE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28575 | call_trace.addresses[call_trace.size] = this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28576 | call_trace.size++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28577 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28578 | call_trace.missed_cnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28579 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28580 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28581 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28582 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28583 | IRAM void __cyg_profile_func_exit(void *this_fn, void *call_site) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28584 | #if defined(V7_STACK_GUARD_MIN_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28585 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28586 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28587 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28588 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28589 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28591 | #if defined(V7_ENABLE_GC_CHECK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28592 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28593 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28594 | void *fp = __builtin_frame_address(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28595 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28596 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28597 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28599 | for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28600 | v7_val_t **vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28601 | if (v7->owned_values.buf == NULL) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28602 | vp = (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - |
Marko Mikulicic |
0:c0ecb8bf28eb | 28603 | sizeof(v7_val_t *)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28605 | for (; (char *) vp >= v7->owned_values.buf; vp--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28606 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28607 | * Check if a variable belongs to a dead stack frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28608 | * Addresses lower than the parent frame belong to the |
Marko Mikulicic |
0:c0ecb8bf28eb | 28609 | * stack frame of the function about to return. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28610 | * But the heap also usually below the stack and |
Marko Mikulicic |
0:c0ecb8bf28eb | 28611 | * we don't know the end of the stack. But this hook |
Marko Mikulicic |
0:c0ecb8bf28eb | 28612 | * is called at each function return, so we have |
Marko Mikulicic |
0:c0ecb8bf28eb | 28613 | * to check only up to the maximum stack frame size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28614 | * let's arbitrarily but reasonably set that at 8k. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28615 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28616 | if ((void *) *vp <= fp && (void *) *vp > (fp + 8196)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28617 | fprintf(stderr, "Found owned variable after return\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28618 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28619 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28620 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28621 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28623 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28624 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28625 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28626 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28627 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28628 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28629 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28630 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28632 | #if defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28633 | if (call_trace.missed_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28634 | call_trace.missed_cnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28635 | } else if (call_trace.size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28636 | if (call_trace.addresses[call_trace.size - 1] != this_fn) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28637 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28638 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28639 | call_trace.size--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28640 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28641 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28642 | * We may get here if calls to `__cyg_profile_func_exit()` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 28643 | * `__cyg_profile_func_enter()` are unbalanced. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28644 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 28645 | * TODO(dfrank) understand, why in the beginning of the program execution |
Marko Mikulicic |
0:c0ecb8bf28eb | 28646 | * we get here. I was sure this should be impossible. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28647 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28648 | /* abort(); */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28649 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28650 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28651 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28652 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28653 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28655 | void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28656 | /* insert new context at the head of the list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28657 | ctx->next = v7->stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28658 | v7->stack_track_ctx = ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28659 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28660 | /* init both `max` and `start` to the current frame pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28661 | ctx->max = ctx->start = __builtin_frame_address(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28662 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28664 | int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28665 | int diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28667 | /* this function can be called only for the head context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28668 | assert(v7->stack_track_ctx == ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28670 | diff = (int) ((char *) ctx->start - (char *) ctx->max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28672 | /* remove context from the linked list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28673 | v7->stack_track_ctx = ctx->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28675 | return (int) diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28678 | #endif /* V7_ENABLE_STACK_TRACKING */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28679 | #endif /* V7_CYG_PROFILE_ON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28680 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 28681 | #line 1 "v7/src/std_object.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 28682 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28683 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28684 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 28685 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 28686 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28687 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28688 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28689 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28690 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28691 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28692 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28693 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28694 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28695 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28696 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28697 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28698 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28699 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28700 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28702 | #if V7_ENABLE__Object__getPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 28703 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28704 | V7_PRIVATE enum v7_err Obj_getPrototypeOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28705 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28706 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28708 | if (!v7_is_object(arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28709 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 28710 | v7_throwf(v7, TYPE_ERROR, "Object.getPrototypeOf called on non-object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28711 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28712 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28713 | *res = v7_get_proto(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28714 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28715 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28716 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28717 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28718 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28719 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28720 | #if V7_ENABLE__Object__isPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 28721 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28722 | V7_PRIVATE enum v7_err Obj_isPrototypeOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28723 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28724 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28725 | val_t proto = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28727 | *res = v7_mk_boolean(v7, is_prototype_of(v7, obj, proto)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28729 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28731 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28732 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28733 | #if V7_ENABLE__Object__getOwnPropertyNames || V7_ENABLE__Object__keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 28734 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28735 | * Hack to ensure that the iteration order of the keys array is consistent |
Marko Mikulicic |
0:c0ecb8bf28eb | 28736 | * with the iteration order if properties in `for in` |
Marko Mikulicic |
0:c0ecb8bf28eb | 28737 | * This will be obsoleted when arrays will have a special object type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28738 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28739 | static void _Obj_append_reverse(struct v7 *v7, struct v7_property *p, val_t res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28740 | int i, v7_prop_attr_t ignore_flags) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28741 | while (p && p->attributes & ignore_flags) p = p->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28742 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28743 | if (p->next) _Obj_append_reverse(v7, p->next, res, i + 1, ignore_flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28745 | v7_array_set(v7, res, i, p->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28746 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28748 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28749 | static enum v7_err _Obj_ownKeys(struct v7 *v7, unsigned int ignore_flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28750 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28751 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28752 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28754 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28756 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28757 | rcode = v7_throwf(v7, TYPE_ERROR, "Object.keys called on non-object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28758 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28759 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28760 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28761 | _Obj_append_reverse(v7, get_object_struct(obj)->properties, *res, 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28762 | ignore_flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28764 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28765 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28767 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28768 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28769 | #if V7_ENABLE__Object__hasOwnProperty || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28770 | V7_ENABLE__Object__propertyIsEnumerable || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28771 | V7_ENABLE__Object__getOwnPropertyDescriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 28772 | static enum v7_err _Obj_getOwnProperty(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28773 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28774 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28775 | char name_buf[512]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28776 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28778 | rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28779 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28780 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28781 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28783 | *res = v7_get_own_property(v7, obj, name_buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28785 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28786 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28788 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28789 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28790 | #if V7_ENABLE__Object__keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 28791 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28792 | V7_PRIVATE enum v7_err Obj_keys(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28793 | return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28794 | res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28796 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28798 | #if V7_ENABLE__Object__getOwnPropertyNames |
Marko Mikulicic |
0:c0ecb8bf28eb | 28799 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28800 | V7_PRIVATE enum v7_err Obj_getOwnPropertyNames(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28801 | return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28803 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28804 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28805 | #if V7_ENABLE__Object__getOwnPropertyDescriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 28806 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28807 | V7_PRIVATE enum v7_err Obj_getOwnPropertyDescriptor(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28808 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28809 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28810 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28811 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28812 | val_t name = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28813 | val_t desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28815 | rcode = _Obj_getOwnProperty(v7, obj, name, &prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28816 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28817 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28818 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28820 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28821 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28822 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28824 | desc = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28825 | v7_set(v7, desc, "value", 5, prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28826 | v7_set(v7, desc, "writable", 8, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28827 | v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_WRITABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28828 | v7_set(v7, desc, "enumerable", 10, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28829 | v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28830 | V7_PROPERTY_NON_ENUMERABLE)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28831 | v7_set(v7, desc, "configurable", 12, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28832 | v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_CONFIGURABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28834 | *res = desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28836 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28837 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28838 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28839 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28841 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28842 | static enum v7_err o_set_attr(struct v7 *v7, val_t desc, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28843 | size_t n, v7_prop_attr_desc_t *pattrs_delta, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28844 | v7_prop_attr_desc_t flag_true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28845 | v7_prop_attr_desc_t flag_false) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28846 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28848 | val_t v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28849 | rcode = v7_get_throwing(v7, desc, name, n, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28850 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28851 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28852 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28854 | if (v7_is_truthy(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28855 | *pattrs_delta |= flag_true; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28856 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28857 | *pattrs_delta |= flag_false; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28859 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28860 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28861 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28862 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28863 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28864 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28865 | static enum v7_err _Obj_defineProperty(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28866 | const char *name, int name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28867 | val_t desc, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28868 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28869 | val_t val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28870 | v7_prop_attr_desc_t attrs_desc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28872 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28873 | * get provided value, or set `V7_DESC_PRESERVE_VALUE` flag if no value is |
Marko Mikulicic |
0:c0ecb8bf28eb | 28874 | * provided at all |
Marko Mikulicic |
0:c0ecb8bf28eb | 28875 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28876 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28877 | struct v7_property *prop = v7_get_property(v7, desc, "value", 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28878 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28879 | /* no value is provided */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28880 | attrs_desc |= V7_DESC_PRESERVE_VALUE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28881 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28882 | /* value is provided: use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28883 | rcode = v7_property_value(v7, desc, prop, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28884 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28885 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28887 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28890 | /* Examine given properties, and set appropriate flags for `def_property` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28892 | rcode = o_set_attr(v7, desc, "enumerable", 10, &attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28893 | V7_DESC_ENUMERABLE(1), V7_DESC_ENUMERABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28894 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28895 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28898 | rcode = o_set_attr(v7, desc, "writable", 8, &attrs_desc, V7_DESC_WRITABLE(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 28899 | V7_DESC_WRITABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28900 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28901 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28902 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28904 | rcode = o_set_attr(v7, desc, "configurable", 12, &attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28905 | V7_DESC_CONFIGURABLE(1), V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28906 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28907 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28908 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28910 | /* TODO(dfrank) : add getter/setter support */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28912 | /* Finally, do the job on defining the property */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28913 | rcode = def_property(v7, obj, name, name_len, attrs_desc, val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28914 | 0 /*not assign*/, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28915 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28916 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28917 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28918 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28919 | *res = obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28920 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28922 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28923 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28924 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28926 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28927 | V7_PRIVATE enum v7_err Obj_defineProperty(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28928 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28929 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28930 | val_t name = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28931 | val_t desc = v7_arg(v7, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28932 | char name_buf[512]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28933 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28935 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28936 | rcode = v7_throwf(v7, TYPE_ERROR, "object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28937 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28938 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28940 | rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28941 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28942 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28943 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28945 | rcode = _Obj_defineProperty(v7, obj, name_buf, name_len, desc, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28946 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28948 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28949 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28950 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28952 | #if V7_ENABLE__Object__create || V7_ENABLE__Object__defineProperties |
Marko Mikulicic |
0:c0ecb8bf28eb | 28953 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28954 | static enum v7_err o_define_props(struct v7 *v7, val_t obj, val_t descs, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28955 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28956 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28957 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28959 | if (!v7_is_object(descs)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28960 | rcode = v7_throwf(v7, TYPE_ERROR, "object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28961 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28964 | for (p = get_object_struct(descs)->properties; p; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28965 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28966 | const char *s = v7_get_string(v7, &p->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28967 | if (p->attributes & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28968 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28970 | rcode = _Obj_defineProperty(v7, obj, s, n, p->value, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28971 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28972 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28973 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28974 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28975 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28976 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28977 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28978 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28979 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28981 | #if V7_ENABLE__Object__defineProperties |
Marko Mikulicic |
0:c0ecb8bf28eb | 28982 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28983 | V7_PRIVATE enum v7_err Obj_defineProperties(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28984 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28985 | val_t descs = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28987 | *res = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28988 | descs = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28989 | rcode = o_define_props(v7, *res, descs, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28990 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28991 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28994 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28995 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28996 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28997 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28999 | #if V7_ENABLE__Object__create |
Marko Mikulicic |
0:c0ecb8bf28eb | 29000 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29001 | V7_PRIVATE enum v7_err Obj_create(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29002 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29003 | val_t proto = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29004 | val_t descs = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29005 | if (!v7_is_null(proto) && !v7_is_object(proto)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29006 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29007 | "Object prototype may only be an Object or null"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29008 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29009 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29010 | *res = mk_object(v7, proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29011 | if (v7_is_object(descs)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29012 | rcode = o_define_props(v7, *res, descs, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29013 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29014 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29015 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29016 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29018 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29019 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29020 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29021 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29022 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29023 | #if V7_ENABLE__Object__propertyIsEnumerable |
Marko Mikulicic |
0:c0ecb8bf28eb | 29024 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29025 | V7_PRIVATE enum v7_err Obj_propertyIsEnumerable(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29026 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29027 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29028 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29029 | val_t name = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29031 | rcode = _Obj_getOwnProperty(v7, this_obj, name, &prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29032 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29033 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29034 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29035 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29036 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29037 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29038 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29039 | *res = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29040 | v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29041 | V7_PROPERTY_NON_ENUMERABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29042 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29043 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29044 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29046 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29047 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29049 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29051 | #if V7_ENABLE__Object__hasOwnProperty |
Marko Mikulicic |
0:c0ecb8bf28eb | 29052 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29053 | V7_PRIVATE enum v7_err Obj_hasOwnProperty(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29054 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29055 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29056 | val_t name = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29057 | struct v7_property *ptmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29059 | rcode = _Obj_getOwnProperty(v7, this_obj, name, &ptmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29060 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29061 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29062 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29064 | *res = v7_mk_boolean(v7, ptmp != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29065 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29066 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29067 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29068 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29069 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29070 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29072 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29073 | V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29074 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29075 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29076 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29078 | *res = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29079 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29080 | if (v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29081 | /* res is `this_obj` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29082 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29083 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29085 | p = v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29086 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29087 | *res = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29088 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29089 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29091 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29092 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29093 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29095 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29096 | V7_PRIVATE enum v7_err Obj_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29097 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29098 | val_t ctor, name, this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29099 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29100 | const char *str = "Object"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29101 | size_t name_len = ~0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29103 | if (v7_is_undefined(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29104 | str = "Undefined"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29105 | } else if (v7_is_null(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29106 | str = "Null"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29107 | } else if (v7_is_number(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29108 | str = "Number"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29109 | } else if (v7_is_boolean(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29110 | str = "Boolean"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29111 | } else if (v7_is_string(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29112 | str = "String"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29113 | } else if (v7_is_callable(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29114 | str = "Function"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29115 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29116 | rcode = v7_get_throwing(v7, this_obj, "constructor", ~0, &ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29117 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29118 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29121 | if (!v7_is_undefined(ctor)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29122 | rcode = v7_get_throwing(v7, ctor, "name", ~0, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29123 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29124 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29125 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29126 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29127 | if (!v7_is_undefined(name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29128 | size_t tmp_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29129 | const char *tmp_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29130 | tmp_str = v7_get_string(v7, &name, &tmp_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29131 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29132 | * objects constructed with an anonymous constructor are represented as |
Marko Mikulicic |
0:c0ecb8bf28eb | 29133 | * Object, ch11/11.1/11.1.1/S11.1.1_A4.2.js |
Marko Mikulicic |
0:c0ecb8bf28eb | 29134 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29135 | if (tmp_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29136 | str = tmp_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29137 | name_len = tmp_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29138 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29139 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29140 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29143 | if (name_len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29144 | name_len = strlen(str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29145 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29147 | c_snprintf(buf, sizeof(buf), "[object %.*s]", (int) name_len, str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29148 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29150 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29151 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29152 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29154 | #if V7_ENABLE__Object__preventExtensions |
Marko Mikulicic |
0:c0ecb8bf28eb | 29155 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29156 | V7_PRIVATE enum v7_err Obj_preventExtensions(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29157 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29158 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29159 | if (!v7_is_object(arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29160 | rcode = v7_throwf(v7, TYPE_ERROR, "Object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29161 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29162 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29163 | get_object_struct(arg)->attributes |= V7_OBJ_NOT_EXTENSIBLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29164 | *res = arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29166 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29167 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29168 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29169 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29170 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29171 | #if V7_ENABLE__Object__isExtensible |
Marko Mikulicic |
0:c0ecb8bf28eb | 29172 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29173 | V7_PRIVATE enum v7_err Obj_isExtensible(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29174 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29175 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29177 | if (!v7_is_object(arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29178 | rcode = v7_throwf(v7, TYPE_ERROR, "Object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29179 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29180 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29182 | *res = v7_mk_boolean( |
Marko Mikulicic |
0:c0ecb8bf28eb | 29183 | v7, !(get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29185 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29186 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29187 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29188 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29189 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29190 | #if V7_ENABLE__Object__isFrozen || V7_ENABLE__Object__isSealed |
Marko Mikulicic |
0:c0ecb8bf28eb | 29191 | static enum v7_err is_rigid(struct v7 *v7, v7_val_t *res, int is_frozen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29192 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29193 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29194 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29195 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29196 | if (!v7_is_object(arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29197 | rcode = v7_throwf(v7, TYPE_ERROR, "Object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29198 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29199 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29201 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29203 | if (get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29204 | v7_prop_attr_t attrs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29205 | struct prop_iter_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29206 | memset(&ctx, 0, sizeof(ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29207 | V7_TRY2(init_prop_iter_ctx(v7, arg, 1, &ctx), clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29208 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29209 | V7_TRY2(next_prop(v7, &ctx, NULL, NULL, &attrs, &ok), clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29210 | if (!ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29211 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29212 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29213 | if (!(attrs & V7_PROPERTY_NON_CONFIGURABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29214 | goto clean_iter; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29215 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29216 | if (is_frozen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29217 | if (!(attrs & V7_PROPERTY_SETTER) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29218 | !(attrs & V7_PROPERTY_NON_WRITABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29219 | goto clean_iter; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29220 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29221 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29222 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29223 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29224 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29226 | clean_iter: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29227 | v7_destruct_prop_iter_ctx(v7, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29228 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29229 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29230 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29231 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29232 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29233 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29234 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29236 | #if V7_ENABLE__Object__isSealed |
Marko Mikulicic |
0:c0ecb8bf28eb | 29237 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29238 | V7_PRIVATE enum v7_err Obj_isSealed(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29239 | return is_rigid(v7, res, 0 /* is_frozen */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29240 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29241 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29243 | #if V7_ENABLE__Object__isFrozen |
Marko Mikulicic |
0:c0ecb8bf28eb | 29244 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29245 | V7_PRIVATE enum v7_err Obj_isFrozen(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29246 | return is_rigid(v7, res, 1 /* is_frozen */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29247 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29248 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29249 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29250 | static const char js_function_Object[] = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29251 | "function Object(v) {" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29252 | "if (typeof v === 'boolean') return new Boolean(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29253 | "if (typeof v === 'number') return new Number(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29254 | "if (typeof v === 'string') return new String(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29255 | "if (typeof v === 'date') return new Date(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29256 | "}"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29257 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29258 | V7_PRIVATE void init_object(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29259 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29260 | val_t object, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29261 | /* TODO(mkm): initialize global object without requiring a parser */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29262 | rcode = v7_exec(v7, js_function_Object, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29263 | assert(rcode == V7_OK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29264 | #if defined(NDEBUG) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29265 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29266 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29268 | object = v7_get(v7, v7->vals.global_object, "Object", 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29269 | v7_set(v7, object, "prototype", 9, v7->vals.object_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29270 | v7_def(v7, v7->vals.object_prototype, "constructor", 11, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29271 | V7_DESC_ENUMERABLE(0), object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29272 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29273 | set_method(v7, v7->vals.object_prototype, "toString", Obj_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29274 | #if V7_ENABLE__Object__getPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 29275 | set_cfunc_prop(v7, object, "getPrototypeOf", Obj_getPrototypeOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29276 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29277 | #if V7_ENABLE__Object__getOwnPropertyDescriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 29278 | set_cfunc_prop(v7, object, "getOwnPropertyDescriptor", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29279 | Obj_getOwnPropertyDescriptor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29280 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29282 | /* defineProperty is currently required to perform stdlib initialization */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29283 | set_method(v7, object, "defineProperty", Obj_defineProperty, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29285 | #if V7_ENABLE__Object__defineProperties |
Marko Mikulicic |
0:c0ecb8bf28eb | 29286 | set_cfunc_prop(v7, object, "defineProperties", Obj_defineProperties); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29287 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29288 | #if V7_ENABLE__Object__create |
Marko Mikulicic |
0:c0ecb8bf28eb | 29289 | set_cfunc_prop(v7, object, "create", Obj_create); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29290 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29291 | #if V7_ENABLE__Object__keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 29292 | set_cfunc_prop(v7, object, "keys", Obj_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29293 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29294 | #if V7_ENABLE__Object__getOwnPropertyNames |
Marko Mikulicic |
0:c0ecb8bf28eb | 29295 | set_cfunc_prop(v7, object, "getOwnPropertyNames", Obj_getOwnPropertyNames); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29296 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29297 | #if V7_ENABLE__Object__preventExtensions |
Marko Mikulicic |
0:c0ecb8bf28eb | 29298 | set_method(v7, object, "preventExtensions", Obj_preventExtensions, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29299 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29300 | #if V7_ENABLE__Object__isExtensible |
Marko Mikulicic |
0:c0ecb8bf28eb | 29301 | set_method(v7, object, "isExtensible", Obj_isExtensible, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29302 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29303 | #if V7_ENABLE__Object__isSealed |
Marko Mikulicic |
0:c0ecb8bf28eb | 29304 | set_method(v7, object, "isSealed", Obj_isSealed, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29305 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29306 | #if V7_ENABLE__Object__isFrozen |
Marko Mikulicic |
0:c0ecb8bf28eb | 29307 | set_method(v7, object, "isFrozen", Obj_isFrozen, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29308 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29309 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29310 | #if V7_ENABLE__Object__propertyIsEnumerable |
Marko Mikulicic |
0:c0ecb8bf28eb | 29311 | set_cfunc_prop(v7, v7->vals.object_prototype, "propertyIsEnumerable", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29312 | Obj_propertyIsEnumerable); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29313 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29314 | #if V7_ENABLE__Object__hasOwnProperty |
Marko Mikulicic |
0:c0ecb8bf28eb | 29315 | set_cfunc_prop(v7, v7->vals.object_prototype, "hasOwnProperty", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29316 | Obj_hasOwnProperty); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29317 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29318 | #if V7_ENABLE__Object__isPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 29319 | set_cfunc_prop(v7, v7->vals.object_prototype, "isPrototypeOf", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29320 | Obj_isPrototypeOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29321 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29322 | set_cfunc_prop(v7, v7->vals.object_prototype, "valueOf", Obj_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29323 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29324 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29325 | #line 1 "v7/src/std_error.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29326 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29327 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29328 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29329 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29330 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29332 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29333 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29334 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29335 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29336 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29337 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29338 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29339 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29340 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29342 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29343 | * TODO(dfrank): make the top of v7->call_frame to represent the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 29344 | * frame, and thus get rid of the `CUR_LINENO()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 29345 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29346 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 29347 | #define CALLFRAME_LINENO(call_frame) ((call_frame)->line_no) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29348 | #define CUR_LINENO() (v7->line_no) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29349 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 29350 | #define CALLFRAME_LINENO(call_frame) 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 29351 | #define CUR_LINENO() 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 29352 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29354 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29355 | V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29357 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29358 | static int printf_stack_line(char *p, size_t len, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29359 | int line_no, const char *leading) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29360 | int ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29361 | const char *fn = bcode_get_filename(bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29362 | if (fn == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29363 | fn = "<no filename>"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29366 | if (bcode->func_name_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29367 | /* this is a function's bcode: let's show the function's name as well */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29368 | char *funcname; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29370 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29371 | * read first name from the bcode ops, which is the function name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29372 | * since `func_name_present` is set |
Marko Mikulicic |
0:c0ecb8bf28eb | 29373 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29374 | bcode_next_name(bcode->ops.p, &funcname, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29376 | /* Check if it's an anonymous function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29377 | if (funcname[0] == '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29378 | funcname = (char *) "<anonymous>"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29380 | ret = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29381 | snprintf(p, len, "%s at %s (%s:%d)", leading, funcname, fn, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29382 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29383 | /* it's a file's bcode: show only filename and line number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29384 | ret = snprintf(p, len, "%s at %s:%d", leading, fn, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29385 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29386 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29387 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29389 | static int printf_stack_line_cfunc(char *p, size_t len, v7_cfunction_t *cfunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29390 | const char *leading) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29391 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29393 | #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29394 | int name_len = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29395 | snprintf(NULL, 0, "cfunc_%p", (void *) cfunc) + 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29396 | char *buf = (char *) malloc(name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29398 | snprintf(buf, name_len, "cfunc_%p", (void *) cfunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29399 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 29400 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29401 | * We need this mode only for ecma test reporting, so that the |
Marko Mikulicic |
0:c0ecb8bf28eb | 29402 | * report is not different from one run to another |
Marko Mikulicic |
0:c0ecb8bf28eb | 29403 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29404 | char *buf = (char *) "cfunc"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29405 | (void) cfunc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29406 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29408 | ret = snprintf(p, len, "%s at %s", leading, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29410 | #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29411 | free(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29412 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29413 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29414 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29415 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29417 | static int print_stack_trace(char *p, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29418 | struct v7_call_frame_base *call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29419 | char *p_cur = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29420 | int total_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29422 | assert(call_frame->type_mask == V7_CALL_FRAME_MASK_CFUNC && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29423 | ((struct v7_call_frame_cfunc *) call_frame)->cfunc == Error_ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29424 | call_frame = call_frame->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29426 | while (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29427 | int cur_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29428 | const char *leading = (total_len ? "\n" : ""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29429 | size_t line_len = len - (p_cur - p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29431 | if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29432 | struct bcode *bcode = ((struct v7_call_frame_bcode *) call_frame)->bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29433 | if (bcode != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29434 | cur_len = printf_stack_line(p_cur, line_len, bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29435 | CALLFRAME_LINENO(call_frame), leading); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29436 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29437 | } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29438 | cur_len = printf_stack_line_cfunc( |
Marko Mikulicic |
0:c0ecb8bf28eb | 29439 | p_cur, line_len, ((struct v7_call_frame_cfunc *) call_frame)->cfunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29440 | leading); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29443 | total_len += cur_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29444 | if (p_cur != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29445 | p_cur += cur_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29448 | call_frame = call_frame->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29450 | #if !(V7_ENABLE__StackTrace) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29451 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29452 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29453 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29455 | return total_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29456 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29457 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29459 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29460 | V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29461 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29462 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29463 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29465 | if (v7_is_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29466 | *res = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29467 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29468 | *res = mk_object(v7, v7->vals.error_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29469 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29470 | /* TODO(mkm): set non enumerable but provide toString method */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29471 | v7_set(v7, *res, "message", 7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29473 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29474 | /* Save the stack trace */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29475 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29476 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29477 | val_t st_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29478 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29479 | v7_own(v7, &st_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29481 | len = print_stack_trace(NULL, 0, v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29483 | if (len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29484 | /* Now, create a placeholder for string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29485 | st_v = v7_mk_string(v7, NULL, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29486 | len += 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29488 | /* And fill it with actual data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29489 | print_stack_trace((char *) v7_get_string(v7, &st_v, NULL), len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29490 | v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29492 | v7_set(v7, *res, "stack", ~0, st_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29493 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29494 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29495 | v7_disown(v7, &st_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29497 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29499 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29500 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29502 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29503 | V7_PRIVATE enum v7_err Error_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29504 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29505 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29506 | val_t prefix, msg = v7_get(v7, this_obj, "message", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29508 | if (!v7_is_string(msg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29509 | *res = v7_mk_string(v7, "Error", ~0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29510 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29511 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29513 | prefix = v7_mk_string(v7, "Error: ", ~0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29514 | *res = s_concat(v7, prefix, msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29515 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29517 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29518 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29519 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29521 | static const char *const error_names[] = {TYPE_ERROR, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29522 | REFERENCE_ERROR, INTERNAL_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29523 | RANGE_ERROR, EVAL_ERROR}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29525 | V7_STATIC_ASSERT(ARRAY_SIZE(error_names) == ERROR_CTOR_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29526 | error_name_count_mismatch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29528 | V7_PRIVATE void init_error(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29529 | val_t error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29530 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29532 | error = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29533 | mk_cfunction_obj_with_proto(v7, Error_ctor, 1, v7->vals.error_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29534 | v7_def(v7, v7->vals.global_object, "Error", 5, V7_DESC_ENUMERABLE(0), error); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29535 | set_method(v7, v7->vals.error_prototype, "toString", Error_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29537 | for (i = 0; i < ARRAY_SIZE(error_names); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29538 | error = mk_cfunction_obj_with_proto( |
Marko Mikulicic |
0:c0ecb8bf28eb | 29539 | v7, Error_ctor, 1, mk_object(v7, v7->vals.error_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29540 | v7_def(v7, v7->vals.global_object, error_names[i], strlen(error_names[i]), |
Marko Mikulicic |
0:c0ecb8bf28eb | 29541 | V7_DESC_ENUMERABLE(0), error); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29542 | v7->vals.error_objects[i] = error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29544 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29545 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29546 | #line 1 "v7/src/std_number.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29547 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29548 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29549 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29550 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29551 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29552 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29553 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29554 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29555 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29556 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29557 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29558 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29559 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29560 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29561 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29563 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29564 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29565 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29567 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29568 | V7_PRIVATE enum v7_err Number_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29569 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29570 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29571 | val_t arg0 = v7_argc(v7) == 0 ? v7_mk_number(v7, 0.0) : v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29573 | if (v7_is_number(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29574 | *res = arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29575 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29576 | rcode = to_number_v(v7, arg0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29577 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29578 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29579 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29580 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29582 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29583 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 29584 | get_object_struct(v7->vals.number_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29585 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29586 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29587 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29588 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 29589 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 29590 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29593 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29594 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29597 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29598 | V7_PRIVATE enum v7_err n_to_str(struct v7 *v7, const char *format, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29599 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29600 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29601 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29602 | int len, digits = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29603 | char fmt[10], buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29605 | rcode = to_number_v(v7, arg0, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29606 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29607 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29608 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29610 | if (v7_get_double(v7, arg0) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29611 | digits = (int) v7_get_double(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29612 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29614 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29615 | * NOTE: we don't own `arg0` and `this_obj`, since this function is called |
Marko Mikulicic |
0:c0ecb8bf28eb | 29616 | * from cfunctions only, and GC is inhibited during these calls |
Marko Mikulicic |
0:c0ecb8bf28eb | 29617 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29618 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29619 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29620 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29621 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29624 | snprintf(fmt, sizeof(fmt), format, digits); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29625 | len = snprintf(buf, sizeof(buf), fmt, v7_get_double(v7, this_obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29627 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29628 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29629 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29630 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29631 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29633 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29634 | V7_PRIVATE enum v7_err Number_toFixed(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29635 | return n_to_str(v7, "%%.%dlf", res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29636 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29638 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29639 | V7_PRIVATE enum v7_err Number_toExp(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29640 | return n_to_str(v7, "%%.%de", res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29643 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29644 | V7_PRIVATE enum v7_err Number_toPrecision(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29645 | return Number_toExp(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29646 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29648 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29649 | V7_PRIVATE enum v7_err Number_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29650 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29651 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29652 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29653 | if (!v7_is_number(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29654 | (v7_is_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29655 | v7_get_proto(v7, this_obj) != v7->vals.number_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29656 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29657 | v7_throwf(v7, TYPE_ERROR, "Number.valueOf called on non-number object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29658 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29659 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29661 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29662 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29663 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29664 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29666 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29667 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29668 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29670 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29671 | * Converts a 64 bit signed integer into a string of a given base. |
Marko Mikulicic |
0:c0ecb8bf28eb | 29672 | * Requires space for 65 bytes (64 bit + null terminator) in the result buffer |
Marko Mikulicic |
0:c0ecb8bf28eb | 29673 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29674 | static char *cs_itoa(int64_t value, char *result, int base) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29675 | char *ptr = result, *ptr1 = result, tmp_char; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29676 | int64_t tmp_value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29677 | int64_t sign = value < 0 ? -1 : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29678 | const char *base36 = "0123456789abcdefghijklmnopqrstuvwxyz"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29680 | if (base < 2 || base > 36) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29681 | *result = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29682 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29683 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29684 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29685 | /* let's think positive */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29686 | value = value * sign; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29687 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29688 | tmp_value = value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29689 | value /= base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29690 | *ptr++ = base36[tmp_value - value * base]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29691 | } while (value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29693 | /* sign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29694 | if (sign < 0) *ptr++ = '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29695 | *ptr-- = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29696 | while (ptr1 < ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29697 | tmp_char = *ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29698 | *ptr-- = *ptr1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29699 | *ptr1++ = tmp_char; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29700 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29701 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29702 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29704 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29705 | V7_PRIVATE enum v7_err Number_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29706 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29707 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29708 | val_t radixv = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29709 | char buf[65]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29710 | double d, radix; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29711 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29712 | if (this_obj == v7->vals.number_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29713 | *res = v7_mk_string(v7, "0", 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29714 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29715 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29716 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29717 | /* Make sure this function was called on Number instance */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29718 | if (!v7_is_number(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29719 | !(v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29720 | is_prototype_of(v7, this_obj, v7->vals.number_prototype))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29721 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29722 | "Number.toString called on non-number object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29723 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29724 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29725 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29726 | /* Get number primitive */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29727 | rcode = to_number_v(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29728 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29729 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29732 | /* Get radix if provided, or 10 otherwise */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29733 | if (!v7_is_undefined(radixv)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29734 | rcode = to_number_v(v7, radixv, &radixv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29735 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29736 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29737 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29738 | radix = v7_get_double(v7, radixv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29739 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29740 | radix = 10.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29741 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29743 | d = v7_get_double(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29744 | if (!isnan(d) && (int64_t) d == d && radix >= 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29745 | cs_itoa(d, buf, radix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29746 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29747 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29748 | rcode = to_string(v7, this_obj, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29749 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29750 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29751 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29752 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29754 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29755 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29756 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29758 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29759 | V7_PRIVATE enum v7_err n_isNaN(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29760 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29761 | *res = v7_mk_boolean(v7, !v7_is_number(arg0) || arg0 == V7_TAG_NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29762 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29763 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29764 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29765 | V7_PRIVATE void init_number(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29766 | v7_prop_attr_desc_t attrs_desc = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29767 | (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29768 | val_t num = mk_cfunction_obj_with_proto(v7, Number_ctor, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29769 | v7->vals.number_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29770 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29771 | v7_def(v7, v7->vals.global_object, "Number", 6, V7_DESC_ENUMERABLE(0), num); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29773 | set_cfunc_prop(v7, v7->vals.number_prototype, "toFixed", Number_toFixed); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29774 | set_cfunc_prop(v7, v7->vals.number_prototype, "toPrecision", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29775 | Number_toPrecision); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29776 | set_cfunc_prop(v7, v7->vals.number_prototype, "toExponential", Number_toExp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29777 | set_cfunc_prop(v7, v7->vals.number_prototype, "valueOf", Number_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29778 | set_cfunc_prop(v7, v7->vals.number_prototype, "toString", Number_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29780 | v7_def(v7, num, "MAX_VALUE", 9, attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29781 | v7_mk_number(v7, 1.7976931348623157e+308)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29782 | v7_def(v7, num, "MIN_VALUE", 9, attrs_desc, v7_mk_number(v7, 5e-324)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29783 | #if V7_ENABLE__NUMBER__NEGATIVE_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 29784 | v7_def(v7, num, "NEGATIVE_INFINITY", 17, attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29785 | v7_mk_number(v7, -INFINITY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29786 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29787 | #if V7_ENABLE__NUMBER__POSITIVE_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 29788 | v7_def(v7, num, "POSITIVE_INFINITY", 17, attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29789 | v7_mk_number(v7, INFINITY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29790 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29791 | v7_def(v7, num, "NaN", 3, attrs_desc, V7_TAG_NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29793 | v7_def(v7, v7->vals.global_object, "NaN", 3, attrs_desc, V7_TAG_NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29794 | v7_def(v7, v7->vals.global_object, "isNaN", 5, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 29795 | v7_mk_cfunction(n_isNaN)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29796 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29798 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29799 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29800 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29801 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29802 | #line 1 "v7/src/std_json.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29803 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29804 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29805 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29806 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29807 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29809 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29810 | /* Amalgamated: #include "v7/src/stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29811 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29812 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29813 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29814 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29815 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29817 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29818 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29819 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29821 | #if defined(V7_ALT_JSON_PARSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29822 | extern enum v7_err v7_alt_json_parse(struct v7 *v7, v7_val_t json_string, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29823 | v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29824 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29826 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29827 | V7_PRIVATE enum v7_err Json_stringify(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29828 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29829 | char buf[100], *p = v7_to_json(v7, arg0, buf, sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29830 | *res = v7_mk_string(v7, p, strlen(p), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29831 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29832 | if (p != buf) free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29833 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29834 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29836 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29837 | V7_PRIVATE enum v7_err Json_parse(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29838 | v7_val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29839 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29840 | #if defined(V7_ALT_JSON_PARSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29841 | rcode = v7_alt_json_parse(v7, arg, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29842 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 29843 | rcode = std_eval(v7, arg, V7_UNDEFINED, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29844 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29845 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29848 | V7_PRIVATE void init_json(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29849 | val_t o = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29850 | set_method(v7, o, "stringify", Json_stringify, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29851 | set_method(v7, o, "parse", Json_parse, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29852 | v7_def(v7, v7->vals.global_object, "JSON", 4, V7_DESC_ENUMERABLE(0), o); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29853 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29855 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29856 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29857 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29858 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29859 | #line 1 "v7/src/std_array.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29860 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29861 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29862 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29863 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29864 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29866 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29867 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29868 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29869 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29870 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29871 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29872 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29873 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29874 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29875 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29876 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29878 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29879 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29880 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29882 | struct a_sort_data { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29883 | val_t sort_func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29884 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29886 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29887 | V7_PRIVATE enum v7_err Array_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29888 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29889 | unsigned long i, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29890 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29891 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29892 | *res = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29893 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29894 | * The interpreter passes dense array to C functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 29895 | * However dense array implementation is not yet complete |
Marko Mikulicic |
0:c0ecb8bf28eb | 29896 | * so we don't want to propagate them at each call to Array() |
Marko Mikulicic |
0:c0ecb8bf28eb | 29897 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29898 | len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29899 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29900 | rcode = v7_array_set_throwing(v7, *res, i, v7_arg(v7, i), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29901 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29902 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29903 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29904 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29906 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29907 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29908 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29910 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29911 | V7_PRIVATE enum v7_err Array_push(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29912 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29913 | int i, len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29915 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29917 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29918 | *res = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29919 | rcode = v7_array_push_throwing(v7, v7_get_this(v7), *res, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29920 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29921 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29923 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29925 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29926 | * TODO(dfrank) : we need to implement `length` as a real property, and here |
Marko Mikulicic |
0:c0ecb8bf28eb | 29927 | * we need to set new length and return it (even if the object is not an |
Marko Mikulicic |
0:c0ecb8bf28eb | 29928 | * array) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29929 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29931 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29932 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29933 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29935 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29936 | V7_PRIVATE enum v7_err Array_get_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29937 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29938 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29939 | long len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29941 | if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29942 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29943 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29944 | *res = v7_mk_number(v7, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29946 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29947 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29948 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29949 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29950 | V7_PRIVATE enum v7_err Array_set_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29951 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29952 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29953 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29954 | long new_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29956 | rcode = to_long(v7, v7_arg(v7, 0), -1, &new_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29957 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29958 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29959 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29961 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29962 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29963 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29964 | } else if (new_len < 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 29965 | (v7_is_number(arg0) && (isnan(v7_get_double(v7, arg0)) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 29966 | isinf(v7_get_double(v7, arg0))))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29967 | rcode = v7_throwf(v7, RANGE_ERROR, "Invalid array length"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29968 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29969 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29970 | struct v7_property **p, **next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29971 | long index, max_index = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29972 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29973 | /* Remove all items with an index higher than new_len */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29974 | for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29975 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29976 | const char *s = v7_get_string(v7, &p[0]->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29977 | next = &p[0]->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29978 | index = strtol(s, NULL, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29979 | if (index >= new_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29980 | v7_destroy_property(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29981 | *p = *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29982 | next = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29983 | } else if (index > max_index) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29984 | max_index = index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29985 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29986 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29988 | /* If we have to expand, insert an item with appropriate index */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29989 | if (new_len > 0 && max_index < new_len - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29990 | char buf[40]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29991 | c_snprintf(buf, sizeof(buf), "%ld", new_len - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29992 | v7_set(v7, this_obj, buf, strlen(buf), V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29993 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29994 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29996 | *res = v7_mk_number(v7, new_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29998 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29999 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30002 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30003 | static enum v7_err a_cmp(struct v7 *v7, void *user_data, const void *pa, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30004 | const void *pb, int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30005 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30006 | struct a_sort_data *sort_data = (struct a_sort_data *) user_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30007 | val_t a = *(val_t *) pa, b = *(val_t *) pb, func = sort_data->sort_func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30009 | if (v7_is_callable(v7, func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30010 | int saved_inhibit_gc = v7->inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30011 | val_t vres = V7_UNDEFINED, args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30012 | v7_array_push(v7, args, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30013 | v7_array_push(v7, args, b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30014 | v7->inhibit_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30015 | rcode = b_apply(v7, func, V7_UNDEFINED, args, 0, &vres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30016 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30017 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30019 | v7->inhibit_gc = saved_inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30020 | *res = (int) -v7_get_double(v7, vres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30021 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30022 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30023 | char sa[100], sb[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30024 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30025 | rcode = to_string(v7, a, NULL, sa, sizeof(sa), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30026 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30027 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30028 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30029 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30030 | rcode = to_string(v7, b, NULL, sb, sizeof(sb), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30031 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30032 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30033 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30035 | sa[sizeof(sa) - 1] = sb[sizeof(sb) - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30036 | *res = strcmp(sb, sa); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30037 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30038 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30040 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30041 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30042 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30043 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30044 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30045 | static enum v7_err a_partition(struct v7 *v7, val_t *a, int l, int r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30046 | void *user_data, int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30047 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30048 | val_t t, pivot = a[l]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30049 | int i = l, j = r + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30051 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30052 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30053 | ++i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30054 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30055 | if (i <= r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30056 | int tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30057 | rcode = a_cmp(v7, user_data, &a[i], &pivot, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30058 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30059 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30061 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30062 | if (tmp > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30063 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30064 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30065 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30066 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30068 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30069 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30070 | int tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30071 | --j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30073 | rcode = a_cmp(v7, user_data, &a[j], &pivot, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30074 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30075 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30076 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30078 | if (tmp <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30079 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30080 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30082 | if (i >= j) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30083 | t = a[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30084 | a[i] = a[j]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30085 | a[j] = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30086 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30087 | t = a[l]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30088 | a[l] = a[j]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30089 | a[j] = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30091 | *res = j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30092 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30093 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30094 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30095 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30096 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30097 | static enum v7_err a_qsort(struct v7 *v7, val_t *a, int l, int r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30098 | void *user_data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30099 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30100 | if (l < r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30101 | int j = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30102 | rcode = a_partition(v7, a, l, r, user_data, &j); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30103 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30104 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30105 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30106 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30107 | rcode = a_qsort(v7, a, l, j - 1, user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30108 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30109 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30110 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30112 | rcode = a_qsort(v7, a, j + 1, r, user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30113 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30114 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30115 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30116 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30117 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30118 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30121 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30122 | static enum v7_err a_sort(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30123 | enum v7_err (*sorting_func)(struct v7 *v7, void *, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30124 | const void *, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30125 | const void *, int *res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30126 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30127 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30128 | int i = 0, len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30129 | val_t *arr = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30130 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30132 | *res = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30133 | len = v7_array_length(v7, *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30135 | if (!v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30136 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30137 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30139 | arr = (val_t *) malloc(len * sizeof(arr[0])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30141 | assert(*res != v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30143 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30144 | arr[i] = v7_array_get(v7, *res, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30145 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30147 | /* TODO(dfrank): sorting_func isn't actually used! something is wrong here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30148 | if (sorting_func != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30149 | struct a_sort_data sort_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30150 | sort_data.sort_func = arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30151 | rcode = a_qsort(v7, arr, 0, len - 1, &sort_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30152 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30153 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30155 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30157 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30158 | v7_array_set(v7, *res, i, arr[len - (i + 1)]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30159 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30161 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30162 | if (arr != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30163 | free(arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30164 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30165 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30166 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30167 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30168 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30169 | V7_PRIVATE enum v7_err Array_sort(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30170 | return a_sort(v7, a_cmp, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30171 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30173 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30174 | V7_PRIVATE enum v7_err Array_reverse(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30175 | return a_sort(v7, NULL, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30176 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30177 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30178 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30179 | V7_PRIVATE enum v7_err Array_join(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30180 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30181 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30182 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30183 | size_t sep_size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30184 | const char *sep = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30186 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30187 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30188 | /* Get pointer to the separator string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30189 | if (!v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30190 | /* If no separator is provided, use comma */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30191 | arg0 = v7_mk_string(v7, ",", 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30193 | sep = v7_get_string(v7, &arg0, &sep_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30195 | /* Do the actual join */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30196 | if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30197 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30198 | char buf[100], *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30199 | long i, n, num_elems = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30201 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30203 | for (i = 0; i < num_elems; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30204 | /* Append separator */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30205 | if (i > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30206 | mbuf_append(&m, sep, sep_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30207 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30209 | /* Append next item from an array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30210 | p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30211 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30212 | size_t tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30213 | rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30214 | sizeof(buf), &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30215 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30216 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30217 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30218 | n = tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30219 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30220 | if (n > (long) sizeof(buf)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30221 | p = (char *) malloc(n + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30222 | rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, p, n, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30223 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30224 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30225 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30226 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30227 | mbuf_append(&m, p, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30228 | if (p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30229 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30230 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30232 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30233 | /* mbuf contains concatenated string now. Copy it to the result. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30234 | *res = v7_mk_string(v7, m.buf, m.len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30235 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30236 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30238 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30239 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30240 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30242 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30243 | V7_PRIVATE enum v7_err Array_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30244 | return Array_join(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30245 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30246 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30247 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30248 | static enum v7_err a_splice(struct v7 *v7, int mutate, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30249 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30250 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30251 | long i, len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30252 | long num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30253 | long elems_to_insert = num_args > 2 ? num_args - 2 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30254 | long arg0, arg1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30256 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30257 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30258 | "Array.splice or Array.slice called on non-object value"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30259 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30260 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30262 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30263 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30264 | rcode = to_long(v7, v7_arg(v7, 0), 0, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30265 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30266 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30267 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30268 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30269 | rcode = to_long(v7, v7_arg(v7, 1), len, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30270 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30271 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30272 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30274 | /* Bounds check */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30275 | if (!mutate && len <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30276 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30277 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30278 | if (arg0 < 0) arg0 = len + arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30279 | if (arg0 < 0) arg0 = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30280 | if (arg0 > len) arg0 = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30281 | if (mutate) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30282 | if (arg1 < 0) arg1 = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30283 | arg1 += arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30284 | } else if (arg1 < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30285 | arg1 = len + arg1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30286 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30288 | /* Create return value - slice */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30289 | for (i = arg0; i < arg1 && i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30290 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 30291 | v7_array_push_throwing(v7, *res, v7_array_get(v7, this_obj, i), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30292 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30293 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30294 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30297 | if (mutate && get_object_struct(this_obj)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30298 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30299 | * dense arrays are spliced by memmoving leaving the trailing |
Marko Mikulicic |
0:c0ecb8bf28eb | 30300 | * space allocated for future appends. |
Marko Mikulicic |
0:c0ecb8bf28eb | 30301 | * TODO(mkm): figure out if trimming is better |
Marko Mikulicic |
0:c0ecb8bf28eb | 30302 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30303 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 30304 | v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30305 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30306 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30307 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30308 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30309 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30310 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30311 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30314 | memmove(abuf->buf + arg0 * sizeof(val_t), abuf->buf + arg1 * sizeof(val_t), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30315 | (len - arg1) * sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30316 | abuf->len -= (arg1 - arg0) * sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30317 | } else if (mutate) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30318 | /* If splicing, modify this_obj array: remove spliced sub-array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30319 | struct v7_property **p, **next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30320 | long i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30322 | for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30323 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30324 | const char *s = v7_get_string(v7, &p[0]->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30325 | next = &p[0]->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30326 | i = strtol(s, NULL, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30327 | if (i >= arg0 && i < arg1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30328 | /* Remove items from spliced sub-array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30329 | v7_destroy_property(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30330 | *p = *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30331 | next = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30332 | } else if (i >= arg1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30333 | /* Modify indices of the elements past sub-array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30334 | char key[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30335 | size_t n = c_snprintf(key, sizeof(key), "%ld", |
Marko Mikulicic |
0:c0ecb8bf28eb | 30336 | i - (arg1 - arg0) + elems_to_insert); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30337 | p[0]->name = v7_mk_string(v7, key, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30338 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30339 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30341 | /* Insert optional extra elements */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30342 | for (i = 2; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30343 | char key[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30344 | size_t n = c_snprintf(key, sizeof(key), "%ld", arg0 + i - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30345 | rcode = set_property(v7, this_obj, key, n, v7_arg(v7, i), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30346 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30347 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30348 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30349 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30350 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30352 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30353 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30354 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30356 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30357 | V7_PRIVATE enum v7_err Array_slice(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30358 | return a_splice(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30361 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30362 | V7_PRIVATE enum v7_err Array_splice(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30363 | return a_splice(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30366 | static void a_prep1(struct v7 *v7, val_t t, val_t *a0, val_t *a1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30367 | *a0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30368 | *a1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30369 | if (v7_is_undefined(*a1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30370 | *a1 = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30371 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30372 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30374 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30375 | * Call callback function `cb`, passing `this_obj` as `this`, with the |
Marko Mikulicic |
0:c0ecb8bf28eb | 30376 | * following arguments: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30377 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 30378 | * cb(v, n, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30379 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 30380 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30381 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30382 | static enum v7_err a_prep2(struct v7 *v7, val_t cb, val_t v, val_t n, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30383 | val_t this_obj, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30384 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30385 | int saved_inhibit_gc = v7->inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30386 | val_t args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30388 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30390 | v7_own(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30391 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30392 | v7_array_push(v7, args, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30393 | v7_array_push(v7, args, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30394 | v7_array_push(v7, args, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30396 | v7->inhibit_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30397 | rcode = b_apply(v7, cb, this_obj, args, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30398 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30399 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30400 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30402 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30403 | v7->inhibit_gc = saved_inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30404 | v7_disown(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30406 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30409 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30410 | V7_PRIVATE enum v7_err Array_forEach(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30411 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30412 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30413 | val_t v = V7_UNDEFINED, cb = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30414 | unsigned long len, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30415 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30416 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30417 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30419 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30420 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30421 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30422 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30424 | if (!v7_is_callable(v7, cb)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30425 | rcode = v7_throwf(v7, TYPE_ERROR, "Function expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30426 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30427 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30429 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30431 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30432 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30433 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30434 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30436 | rcode = a_prep2(v7, cb, v, v7_mk_number(v7, i), this_obj, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30437 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30438 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30439 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30440 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30442 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30443 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30444 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30445 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30446 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30447 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30448 | V7_PRIVATE enum v7_err Array_map(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30449 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30450 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30451 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30452 | unsigned long len, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30453 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30454 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30455 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30457 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30458 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30459 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30460 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30461 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30462 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30463 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30465 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30466 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30467 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30469 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30470 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30471 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30472 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30473 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30474 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30475 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30477 | rcode = v7_array_set_throwing(v7, *res, i, el, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30478 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30479 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30481 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30482 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30484 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30485 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30486 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30489 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30490 | V7_PRIVATE enum v7_err Array_every(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30491 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30492 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30493 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30494 | unsigned long i, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30495 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30496 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30497 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30499 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30500 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30501 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30502 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30503 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30504 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30505 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30507 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30508 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30509 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30511 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30512 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30513 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30514 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30515 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30516 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30517 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30518 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30519 | if (!v7_is_truthy(v7, el)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30520 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30521 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30522 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30525 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30526 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30528 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30529 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30530 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30531 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30533 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30534 | V7_PRIVATE enum v7_err Array_some(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30535 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30536 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30537 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30538 | unsigned long i, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30539 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30540 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30541 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30542 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30543 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30544 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30545 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30546 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30547 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30548 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30549 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30550 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30551 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30552 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30553 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30555 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30556 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30557 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30558 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30559 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30560 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30561 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30562 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30563 | if (v7_is_truthy(v7, el)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30564 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30565 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30566 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30567 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30568 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30570 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30572 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30573 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30574 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30575 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30576 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30577 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30578 | V7_PRIVATE enum v7_err Array_filter(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30579 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30580 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30581 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30582 | unsigned long len, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30583 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30584 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30585 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30586 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30587 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30588 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30589 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30590 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30591 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30592 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30593 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30594 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30595 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30596 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30597 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30599 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30600 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30601 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30602 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30603 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30604 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30605 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30606 | if (v7_is_truthy(v7, el)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30607 | rcode = v7_array_push_throwing(v7, *res, v, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30608 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30609 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30610 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30611 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30612 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30613 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30615 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30616 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30617 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30618 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30620 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30621 | V7_PRIVATE enum v7_err Array_concat(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30622 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30623 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30624 | size_t i, j, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30625 | val_t saved_args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30627 | if (!v7_is_array(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30628 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30629 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30632 | len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30634 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30635 | * reuse a_splice but override it's arguments. a_splice |
Marko Mikulicic |
0:c0ecb8bf28eb | 30636 | * internally uses a lot of helpers that fetch arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 30637 | * from the v7 context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 30638 | * TODO(mkm): we need a better helper call another cfunction |
Marko Mikulicic |
0:c0ecb8bf28eb | 30639 | * from a cfunction. |
Marko Mikulicic |
0:c0ecb8bf28eb | 30640 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30641 | saved_args = v7->vals.arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30642 | v7->vals.arguments = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30643 | rcode = a_splice(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30644 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30645 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30646 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30647 | v7->vals.arguments = saved_args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30649 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30650 | val_t a = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30651 | if (!v7_is_array(v7, a)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30652 | rcode = v7_array_push_throwing(v7, *res, a, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30653 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30654 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30655 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30656 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30657 | size_t alen = v7_array_length(v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30658 | for (j = 0; j < alen; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30659 | rcode = v7_array_push_throwing(v7, *res, v7_array_get(v7, a, j), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30660 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30661 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30662 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30663 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30664 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30665 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30667 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30668 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30669 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30671 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30672 | V7_PRIVATE enum v7_err Array_isArray(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30673 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30674 | *res = v7_mk_boolean(v7, v7_is_array(v7, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30675 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30678 | V7_PRIVATE void init_array(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30679 | val_t ctor = mk_cfunction_obj(v7, Array_ctor, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30680 | val_t length = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30682 | v7_set(v7, ctor, "prototype", 9, v7->vals.array_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30683 | set_method(v7, ctor, "isArray", Array_isArray, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30684 | v7_set(v7, v7->vals.global_object, "Array", 5, ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30685 | v7_def(v7, v7->vals.array_prototype, "constructor", ~0, _V7_DESC_HIDDEN(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30686 | ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30687 | v7_set(v7, ctor, "name", 4, v7_mk_string(v7, "Array", ~0, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30689 | set_method(v7, v7->vals.array_prototype, "concat", Array_concat, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30690 | set_method(v7, v7->vals.array_prototype, "every", Array_every, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30691 | set_method(v7, v7->vals.array_prototype, "filter", Array_filter, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30692 | set_method(v7, v7->vals.array_prototype, "forEach", Array_forEach, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30693 | set_method(v7, v7->vals.array_prototype, "join", Array_join, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30694 | set_method(v7, v7->vals.array_prototype, "map", Array_map, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30695 | set_method(v7, v7->vals.array_prototype, "push", Array_push, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30696 | set_method(v7, v7->vals.array_prototype, "reverse", Array_reverse, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30697 | set_method(v7, v7->vals.array_prototype, "slice", Array_slice, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30698 | set_method(v7, v7->vals.array_prototype, "some", Array_some, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30699 | set_method(v7, v7->vals.array_prototype, "sort", Array_sort, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30700 | set_method(v7, v7->vals.array_prototype, "splice", Array_splice, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30701 | set_method(v7, v7->vals.array_prototype, "toString", Array_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30702 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30703 | v7_array_set(v7, length, 0, v7_mk_cfunction(Array_get_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30704 | v7_array_set(v7, length, 1, v7_mk_cfunction(Array_set_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30705 | v7_def(v7, v7->vals.array_prototype, "length", 6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30706 | V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1) | V7_DESC_SETTER(1), length); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30707 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30708 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30709 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30710 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30711 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30712 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 30713 | #line 1 "v7/src/std_boolean.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 30714 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30715 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30716 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 30717 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 30718 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30719 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30720 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30721 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30722 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30723 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30724 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30725 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30726 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30727 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30728 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30730 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30731 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30732 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30733 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30734 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30735 | V7_PRIVATE enum v7_err Boolean_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30736 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30737 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30739 | *res = to_boolean_v(v7, v7_arg(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30741 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30742 | /* called as "new Boolean(...)" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30743 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30744 | get_object_struct(v7->vals.boolean_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30745 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30746 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30747 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30748 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 30749 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 30750 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30751 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30753 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30754 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30756 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30757 | V7_PRIVATE enum v7_err Boolean_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30758 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30759 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30760 | if (!v7_is_boolean(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30761 | (v7_is_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30762 | v7_get_proto(v7, this_obj) != v7->vals.boolean_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30763 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30764 | "Boolean.valueOf called on non-boolean object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30765 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30768 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30769 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30770 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30771 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30773 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30774 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30775 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30777 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30778 | V7_PRIVATE enum v7_err Boolean_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30779 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30780 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30781 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30782 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30784 | if (this_obj == v7->vals.boolean_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30785 | *res = v7_mk_string(v7, "false", 5, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30786 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30789 | if (!v7_is_boolean(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30790 | !(v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30791 | is_prototype_of(v7, this_obj, v7->vals.boolean_prototype))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30792 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30793 | "Boolean.toString called on non-boolean object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30794 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30797 | rcode = obj_value_of(v7, this_obj, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30798 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30799 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30800 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30802 | rcode = primitive_to_str(v7, *res, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30803 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30804 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30805 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30806 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30807 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30808 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30809 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30811 | V7_PRIVATE void init_boolean(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30812 | val_t ctor = mk_cfunction_obj_with_proto(v7, Boolean_ctor, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30813 | v7->vals.boolean_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30814 | v7_set(v7, v7->vals.global_object, "Boolean", 7, ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30816 | set_cfunc_prop(v7, v7->vals.boolean_prototype, "valueOf", Boolean_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30817 | set_cfunc_prop(v7, v7->vals.boolean_prototype, "toString", Boolean_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30818 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30820 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30822 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30823 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 30824 | #line 1 "v7/src/std_math.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 30825 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30826 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30827 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 30828 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 30829 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30831 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30832 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30833 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30834 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30836 | #if V7_ENABLE__Math |
Marko Mikulicic |
0:c0ecb8bf28eb | 30837 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30838 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30839 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30840 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30842 | #ifdef __WATCOM__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30843 | int matherr(struct _exception *exc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30844 | if (exc->type == DOMAIN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30845 | exc->retval = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30846 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30848 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30849 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30850 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30851 | #if V7_ENABLE__Math__abs || V7_ENABLE__Math__acos || V7_ENABLE__Math__asin || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30852 | V7_ENABLE__Math__atan || V7_ENABLE__Math__ceil || V7_ENABLE__Math__cos || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30853 | V7_ENABLE__Math__exp || V7_ENABLE__Math__floor || V7_ENABLE__Math__log || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30854 | V7_ENABLE__Math__round || V7_ENABLE__Math__sin || V7_ENABLE__Math__sqrt || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30855 | V7_ENABLE__Math__tan |
Marko Mikulicic |
0:c0ecb8bf28eb | 30856 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30857 | static enum v7_err m_one_arg(struct v7 *v7, double (*f)(double), val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30858 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30859 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30860 | double d0 = v7_get_double(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30861 | #ifdef V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 30862 | if (isnan(d0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30863 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30864 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30866 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30867 | *res = v7_mk_number(v7, f(d0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30868 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30869 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30870 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30871 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30872 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30873 | #endif /* V7_ENABLE__Math__* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30875 | #if V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 30876 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30877 | static enum v7_err m_two_arg(struct v7 *v7, double (*f)(double, double), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30878 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30879 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30880 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30881 | val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30882 | double d0 = v7_get_double(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30883 | double d1 = v7_get_double(v7, arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30884 | #ifdef V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 30885 | /* pow(NaN,0) == 1, doesn't fix atan2, but who cares */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30886 | if (isnan(d1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30887 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30888 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30889 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30890 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30891 | *res = v7_mk_number(v7, f(d0, d1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30892 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30894 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30895 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30897 | #endif /* V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30899 | #define DEFINE_WRAPPER(name, func) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30900 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30901 | V7_PRIVATE enum v7_err Math_##name(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30902 | return func(v7, name, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30903 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30905 | /* Visual studio 2012+ has round() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30906 | #if V7_ENABLE__Math__round && \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30907 | ((defined(V7_WINDOWS) && _MSC_VER < 1700) || defined(__WATCOM__)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30908 | static double round(double n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30909 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30911 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30913 | #if V7_ENABLE__Math__abs |
Marko Mikulicic |
0:c0ecb8bf28eb | 30914 | DEFINE_WRAPPER(fabs, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30915 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30916 | #if V7_ENABLE__Math__acos |
Marko Mikulicic |
0:c0ecb8bf28eb | 30917 | DEFINE_WRAPPER(acos, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30918 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30919 | #if V7_ENABLE__Math__asin |
Marko Mikulicic |
0:c0ecb8bf28eb | 30920 | DEFINE_WRAPPER(asin, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30921 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30922 | #if V7_ENABLE__Math__atan |
Marko Mikulicic |
0:c0ecb8bf28eb | 30923 | DEFINE_WRAPPER(atan, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30924 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30925 | #if V7_ENABLE__Math__atan2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 30926 | DEFINE_WRAPPER(atan2, m_two_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30927 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30928 | #if V7_ENABLE__Math__ceil |
Marko Mikulicic |
0:c0ecb8bf28eb | 30929 | DEFINE_WRAPPER(ceil, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30930 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30931 | #if V7_ENABLE__Math__cos |
Marko Mikulicic |
0:c0ecb8bf28eb | 30932 | DEFINE_WRAPPER(cos, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30933 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30934 | #if V7_ENABLE__Math__exp |
Marko Mikulicic |
0:c0ecb8bf28eb | 30935 | DEFINE_WRAPPER(exp, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30936 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30937 | #if V7_ENABLE__Math__floor |
Marko Mikulicic |
0:c0ecb8bf28eb | 30938 | DEFINE_WRAPPER(floor, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30939 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30940 | #if V7_ENABLE__Math__log |
Marko Mikulicic |
0:c0ecb8bf28eb | 30941 | DEFINE_WRAPPER(log, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30942 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30943 | #if V7_ENABLE__Math__pow |
Marko Mikulicic |
0:c0ecb8bf28eb | 30944 | DEFINE_WRAPPER(pow, m_two_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30945 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30946 | #if V7_ENABLE__Math__round |
Marko Mikulicic |
0:c0ecb8bf28eb | 30947 | DEFINE_WRAPPER(round, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30948 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30949 | #if V7_ENABLE__Math__sin |
Marko Mikulicic |
0:c0ecb8bf28eb | 30950 | DEFINE_WRAPPER(sin, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30951 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30952 | #if V7_ENABLE__Math__sqrt |
Marko Mikulicic |
0:c0ecb8bf28eb | 30953 | DEFINE_WRAPPER(sqrt, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30954 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30955 | #if V7_ENABLE__Math__tan |
Marko Mikulicic |
0:c0ecb8bf28eb | 30956 | DEFINE_WRAPPER(tan, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30957 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30959 | #if V7_ENABLE__Math__random |
Marko Mikulicic |
0:c0ecb8bf28eb | 30960 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30961 | V7_PRIVATE enum v7_err Math_random(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30962 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30963 | *res = v7_mk_number(v7, (double) rand() / RAND_MAX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30964 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30965 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30966 | #endif /* V7_ENABLE__Math__random */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30968 | #if V7_ENABLE__Math__min || V7_ENABLE__Math__max |
Marko Mikulicic |
0:c0ecb8bf28eb | 30969 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30970 | static enum v7_err min_max(struct v7 *v7, int is_min, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30971 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30972 | double dres = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30973 | int i, len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30975 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30976 | double v = v7_get_double(v7, v7_arg(v7, i)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30977 | if (isnan(dres) || (is_min && v < dres) || (!is_min && v > dres)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30978 | dres = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30979 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30980 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30982 | *res = v7_mk_number(v7, dres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30984 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30985 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30986 | #endif /* V7_ENABLE__Math__min || V7_ENABLE__Math__max */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30988 | #if V7_ENABLE__Math__min |
Marko Mikulicic |
0:c0ecb8bf28eb | 30989 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30990 | V7_PRIVATE enum v7_err Math_min(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30991 | return min_max(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30993 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30995 | #if V7_ENABLE__Math__max |
Marko Mikulicic |
0:c0ecb8bf28eb | 30996 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30997 | V7_PRIVATE enum v7_err Math_max(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30998 | return min_max(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30999 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31000 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31002 | V7_PRIVATE void init_math(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31003 | val_t math = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31005 | #if V7_ENABLE__Math__abs |
Marko Mikulicic |
0:c0ecb8bf28eb | 31006 | set_cfunc_prop(v7, math, "abs", Math_fabs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31007 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31008 | #if V7_ENABLE__Math__acos |
Marko Mikulicic |
0:c0ecb8bf28eb | 31009 | set_cfunc_prop(v7, math, "acos", Math_acos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31010 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31011 | #if V7_ENABLE__Math__asin |
Marko Mikulicic |
0:c0ecb8bf28eb | 31012 | set_cfunc_prop(v7, math, "asin", Math_asin); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31013 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31014 | #if V7_ENABLE__Math__atan |
Marko Mikulicic |
0:c0ecb8bf28eb | 31015 | set_cfunc_prop(v7, math, "atan", Math_atan); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31016 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31017 | #if V7_ENABLE__Math__atan2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 31018 | set_cfunc_prop(v7, math, "atan2", Math_atan2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31019 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31020 | #if V7_ENABLE__Math__ceil |
Marko Mikulicic |
0:c0ecb8bf28eb | 31021 | set_cfunc_prop(v7, math, "ceil", Math_ceil); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31022 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31023 | #if V7_ENABLE__Math__cos |
Marko Mikulicic |
0:c0ecb8bf28eb | 31024 | set_cfunc_prop(v7, math, "cos", Math_cos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31025 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31026 | #if V7_ENABLE__Math__exp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31027 | set_cfunc_prop(v7, math, "exp", Math_exp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31028 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31029 | #if V7_ENABLE__Math__floor |
Marko Mikulicic |
0:c0ecb8bf28eb | 31030 | set_cfunc_prop(v7, math, "floor", Math_floor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31031 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31032 | #if V7_ENABLE__Math__log |
Marko Mikulicic |
0:c0ecb8bf28eb | 31033 | set_cfunc_prop(v7, math, "log", Math_log); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31034 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31035 | #if V7_ENABLE__Math__max |
Marko Mikulicic |
0:c0ecb8bf28eb | 31036 | set_cfunc_prop(v7, math, "max", Math_max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31037 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31038 | #if V7_ENABLE__Math__min |
Marko Mikulicic |
0:c0ecb8bf28eb | 31039 | set_cfunc_prop(v7, math, "min", Math_min); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31040 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31041 | #if V7_ENABLE__Math__pow |
Marko Mikulicic |
0:c0ecb8bf28eb | 31042 | set_cfunc_prop(v7, math, "pow", Math_pow); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31043 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31044 | #if V7_ENABLE__Math__random |
Marko Mikulicic |
0:c0ecb8bf28eb | 31045 | /* Incorporate our pointer into the RNG. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31046 | * If srand() has not been called before, this will provide some randomness. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31047 | * If it has, it will hopefully not make things worse. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31048 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31049 | srand(rand() ^ ((uintptr_t) v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31050 | set_cfunc_prop(v7, math, "random", Math_random); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31051 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31052 | #if V7_ENABLE__Math__round |
Marko Mikulicic |
0:c0ecb8bf28eb | 31053 | set_cfunc_prop(v7, math, "round", Math_round); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31054 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31055 | #if V7_ENABLE__Math__sin |
Marko Mikulicic |
0:c0ecb8bf28eb | 31056 | set_cfunc_prop(v7, math, "sin", Math_sin); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31057 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31058 | #if V7_ENABLE__Math__sqrt |
Marko Mikulicic |
0:c0ecb8bf28eb | 31059 | set_cfunc_prop(v7, math, "sqrt", Math_sqrt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31060 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31061 | #if V7_ENABLE__Math__tan |
Marko Mikulicic |
0:c0ecb8bf28eb | 31062 | set_cfunc_prop(v7, math, "tan", Math_tan); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31063 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31065 | #if V7_ENABLE__Math__constants |
Marko Mikulicic |
0:c0ecb8bf28eb | 31066 | v7_set(v7, math, "E", 1, v7_mk_number(v7, M_E)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31067 | v7_set(v7, math, "PI", 2, v7_mk_number(v7, M_PI)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31068 | v7_set(v7, math, "LN2", 3, v7_mk_number(v7, M_LN2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31069 | v7_set(v7, math, "LN10", 4, v7_mk_number(v7, M_LN10)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31070 | v7_set(v7, math, "LOG2E", 5, v7_mk_number(v7, M_LOG2E)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31071 | v7_set(v7, math, "LOG10E", 6, v7_mk_number(v7, M_LOG10E)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31072 | v7_set(v7, math, "SQRT1_2", 7, v7_mk_number(v7, M_SQRT1_2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31073 | v7_set(v7, math, "SQRT2", 5, v7_mk_number(v7, M_SQRT2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31074 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31076 | v7_set(v7, v7->vals.global_object, "Math", 4, math); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31079 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31080 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31081 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31083 | #endif /* V7_ENABLE__Math */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31084 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 31085 | #line 1 "v7/src/std_string.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 31086 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31087 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31088 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 31089 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 31090 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31091 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31092 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31093 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31094 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31095 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31096 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31097 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31098 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31099 | /* Amalgamated: #include "v7/src/std_regex.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31100 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31101 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31102 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31103 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31104 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31105 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31106 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31107 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31108 | /* Substring implementations: RegExp-based and String-based {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31110 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31111 | * Substring context: currently, used in Str_split() only, but will probably |
Marko Mikulicic |
0:c0ecb8bf28eb | 31112 | * be used in Str_replace() and other functions as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31113 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 31114 | * Needed to provide different implementation for RegExp or String arguments, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31115 | * keeping common parts reusable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31116 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31117 | struct _str_split_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31118 | /* implementation-specific data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31119 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31120 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31121 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31122 | struct slre_prog *prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31123 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31124 | } regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31125 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31126 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31127 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31128 | val_t sep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31129 | } string; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31130 | } impl; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31132 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31134 | /* start and end of previous match (set by `p_exec()`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31135 | const char *match_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31136 | const char *match_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31138 | /* pointers to implementation functions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31140 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31141 | * Initialize context |
Marko Mikulicic |
0:c0ecb8bf28eb | 31142 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31143 | void (*p_init)(struct _str_split_ctx *ctx, struct v7 *v7, val_t sep); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31145 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31146 | * Look for the next match, set `match_start` and `match_end` to appropriate |
Marko Mikulicic |
0:c0ecb8bf28eb | 31147 | * values. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31148 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 31149 | * Returns 0 if match found, 1 otherwise (in accordance with `slre_exec()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31150 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31151 | int (*p_exec)(struct _str_split_ctx *ctx, const char *start, const char *end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31153 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31154 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31155 | * Add captured data to resulting array (for RegExp-based implementation only) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31156 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 31157 | * Returns updated `elem` value |
Marko Mikulicic |
0:c0ecb8bf28eb | 31158 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31159 | long (*p_add_caps)(struct _str_split_ctx *ctx, val_t res, long elem, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31160 | long limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31161 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31162 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31164 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31165 | /* RegExp-based implementation of `p_init` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31166 | static void subs_regexp_init(struct _str_split_ctx *ctx, struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31167 | val_t sep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31168 | ctx->v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31169 | ctx->impl.regexp.prog = v7_get_regexp_struct(v7, sep)->compiled_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31170 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31172 | /* RegExp-based implementation of `p_exec` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31173 | static int subs_regexp_exec(struct _str_split_ctx *ctx, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31174 | const char *end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31175 | int ret = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31176 | slre_exec(ctx->impl.regexp.prog, 0, start, end, &ctx->impl.regexp.loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31177 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31178 | ctx->match_start = ctx->impl.regexp.loot.caps[0].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31179 | ctx->match_end = ctx->impl.regexp.loot.caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31180 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31181 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31182 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31183 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31184 | /* RegExp-based implementation of `p_add_caps` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31185 | static long subs_regexp_split_add_caps(struct _str_split_ctx *ctx, val_t res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31186 | long elem, long limit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31187 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31188 | for (i = 1; i < ctx->impl.regexp.loot.num_captures && elem < limit; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31189 | size_t cap_len = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31190 | ctx->impl.regexp.loot.caps[i].end - ctx->impl.regexp.loot.caps[i].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31191 | v7_array_push( |
Marko Mikulicic |
0:c0ecb8bf28eb | 31192 | ctx->v7, res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31193 | (ctx->impl.regexp.loot.caps[i].start != NULL) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31194 | ? v7_mk_string(ctx->v7, ctx->impl.regexp.loot.caps[i].start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31195 | cap_len, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31196 | : V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31197 | elem++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31198 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31199 | return elem; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31201 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31203 | /* String-based implementation of `p_init` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31204 | static void subs_string_init(struct _str_split_ctx *ctx, struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31205 | val_t sep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31206 | ctx->v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31207 | ctx->impl.string.sep = sep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31208 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31210 | /* String-based implementation of `p_exec` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31211 | static int subs_string_exec(struct _str_split_ctx *ctx, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31212 | const char *end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31213 | int ret = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31214 | size_t sep_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31215 | const char *psep = v7_get_string(ctx->v7, &ctx->impl.string.sep, &sep_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31216 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31217 | if (sep_len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31218 | /* separator is an empty string: match empty string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31219 | ctx->match_start = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31220 | ctx->match_end = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31221 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31222 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31223 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31224 | for (i = 0; start <= (end - sep_len); ++i, start = utfnshift(start, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31225 | if (memcmp(start, psep, sep_len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31226 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31227 | ctx->match_start = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31228 | ctx->match_end = start + sep_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31229 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31230 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31232 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31233 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31234 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31235 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31237 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31238 | /* String-based implementation of `p_add_caps` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31239 | static long subs_string_split_add_caps(struct _str_split_ctx *ctx, val_t res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31240 | long elem, long limit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31241 | /* this is a stub function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31242 | (void) ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31243 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31244 | (void) limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31245 | return elem; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31246 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31247 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31249 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31251 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31252 | V7_PRIVATE enum v7_err String_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31253 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31254 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31255 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31257 | *res = arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31258 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31259 | if (v7_argc(v7) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31260 | *res = v7_mk_string(v7, NULL, 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31261 | } else if (!v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31262 | rcode = to_string(v7, arg0, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31263 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31264 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31265 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31266 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31268 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31269 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31270 | get_object_struct(v7->vals.string_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31271 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31272 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31273 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 31274 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 31275 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31276 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31277 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31278 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31279 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31280 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31281 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31283 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31284 | V7_PRIVATE enum v7_err Str_fromCharCode(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31285 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31286 | int i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31288 | *res = v7_mk_string(v7, "", 0, 1); /* Empty string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31290 | for (i = 0; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31291 | char buf[10]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31292 | val_t arg = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31293 | double d = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31294 | Rune r = (Rune)((int32_t)(isnan(d) || isinf(d) ? 0 : d) & 0xffff); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31295 | int n = runetochar(buf, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31296 | val_t s = v7_mk_string(v7, buf, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31297 | *res = s_concat(v7, *res, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31298 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31299 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31300 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31303 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31304 | static enum v7_err s_charCodeAt(struct v7 *v7, double *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31305 | return v7_char_code_at(v7, v7_get_this(v7), v7_arg(v7, 0), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31306 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31308 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31309 | V7_PRIVATE enum v7_err Str_charCodeAt(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31310 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31311 | double dnum = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31312 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31313 | rcode = s_charCodeAt(v7, &dnum); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31314 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31315 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31316 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31318 | *res = v7_mk_number(v7, dnum); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31320 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31321 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31324 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31325 | V7_PRIVATE enum v7_err Str_charAt(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31326 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31327 | double code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31328 | char buf[10] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31329 | int len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31331 | rcode = s_charCodeAt(v7, &code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31332 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31333 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31336 | if (!isnan(code)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31337 | Rune r = (Rune) code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31338 | len = runetochar(buf, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31339 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31340 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31342 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31343 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31346 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31347 | V7_PRIVATE enum v7_err Str_concat(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31348 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31349 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31350 | int i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31352 | rcode = to_string(v7, this_obj, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31353 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31354 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31355 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31357 | for (i = 0; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31358 | val_t str = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31360 | rcode = to_string(v7, v7_arg(v7, i), &str, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31361 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31362 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31365 | *res = s_concat(v7, *res, str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31366 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31367 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31368 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31369 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31370 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31371 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31372 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31373 | static enum v7_err s_index_of(struct v7 *v7, int last, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31374 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31375 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31376 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31377 | size_t fromIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31378 | double dres = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31380 | if (!v7_is_undefined(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31381 | const char *p1, *p2, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31382 | size_t i, len1, len2, bytecnt1, bytecnt2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31383 | val_t sub = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31385 | rcode = to_string(v7, arg0, &sub, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31386 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31387 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31390 | rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31391 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31392 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31394 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31395 | p1 = v7_get_string(v7, &this_obj, &bytecnt1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31396 | p2 = v7_get_string(v7, &sub, &bytecnt2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31398 | if (bytecnt2 <= bytecnt1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31399 | end = p1 + bytecnt1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31400 | len1 = utfnlen(p1, bytecnt1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31401 | len2 = utfnlen(p2, bytecnt2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31402 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31403 | if (v7_argc(v7) > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31404 | /* `fromIndex` was provided. Normalize it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31405 | double d = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31406 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31407 | val_t arg = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31408 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31409 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31410 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31411 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31412 | d = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31413 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31414 | if (isnan(d) || d < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31415 | d = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31416 | } else if (isinf(d) || d > len1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31417 | d = len1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31418 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31419 | fromIndex = d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31421 | /* adjust pointers accordingly to `fromIndex` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31422 | if (last) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31423 | const char *end_tmp = utfnshift(p1, fromIndex + len2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31424 | end = (end_tmp < end) ? end_tmp : end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31425 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31426 | p1 = utfnshift(p1, fromIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31427 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31428 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31430 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31431 | * TODO(dfrank): when `last` is set, start from the end and look |
Marko Mikulicic |
0:c0ecb8bf28eb | 31432 | * backward. We'll need to improve `utfnshift()` for that, so that it can |
Marko Mikulicic |
0:c0ecb8bf28eb | 31433 | * handle negative offsets. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31434 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31435 | for (i = 0; p1 <= (end - bytecnt2); i++, p1 = utfnshift(p1, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31436 | if (memcmp(p1, p2, bytecnt2) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31437 | dres = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31438 | if (!last) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31439 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31440 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31442 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31443 | if (!last && dres >= 0) dres += fromIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31444 | *res = v7_mk_number(v7, dres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31446 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31447 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31448 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31450 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31451 | V7_PRIVATE enum v7_err Str_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31452 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31453 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31455 | if (!v7_is_string(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31456 | (v7_is_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31457 | v7_get_proto(v7, this_obj) != v7->vals.string_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31458 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31459 | v7_throwf(v7, TYPE_ERROR, "String.valueOf called on non-string object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31460 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31463 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31464 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31466 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31467 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31468 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31470 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31471 | V7_PRIVATE enum v7_err Str_indexOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31472 | return s_index_of(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31473 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31475 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31476 | V7_PRIVATE enum v7_err Str_lastIndexOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31477 | return s_index_of(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31478 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31480 | #if V7_ENABLE__String__localeCompare |
Marko Mikulicic |
0:c0ecb8bf28eb | 31481 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31482 | V7_PRIVATE enum v7_err Str_localeCompare(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31483 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31484 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31485 | val_t arg0 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31486 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31488 | rcode = to_string(v7, v7_arg(v7, 0), &arg0, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31489 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31490 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31491 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31493 | rcode = to_string(v7, this_obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31494 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31495 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31497 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31498 | *res = v7_mk_number(v7, s_cmp(v7, s, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31499 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31500 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31501 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31502 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31503 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31505 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31506 | V7_PRIVATE enum v7_err Str_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31507 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31508 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31510 | if (this_obj == v7->vals.string_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31511 | *res = v7_mk_string(v7, "false", 5, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31512 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31513 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31514 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31515 | if (!v7_is_string(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31516 | !(v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31517 | is_prototype_of(v7, this_obj, v7->vals.string_prototype))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31518 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31519 | "String.toString called on non-string object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31520 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31521 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31523 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31524 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31525 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31526 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31528 | rcode = to_string(v7, this_obj, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31529 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31530 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31531 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31533 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31534 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31535 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31537 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31538 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31539 | enum v7_err call_regex_ctor(struct v7 *v7, val_t arg, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31540 | /* TODO(mkm): make general helper out of this */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31541 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31542 | val_t saved_args = v7->vals.arguments, args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31543 | v7_array_push(v7, args, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31544 | v7->vals.arguments = args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31546 | rcode = Regex_ctor(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31547 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31548 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31549 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31550 | v7->vals.arguments = saved_args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31552 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31553 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31554 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31556 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31557 | V7_PRIVATE enum v7_err Str_match(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31558 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31559 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31560 | val_t so = V7_UNDEFINED, ro = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31561 | long previousLastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31562 | int lastMatch = 1, n = 0, flag_g; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31563 | struct v7_regexp *rxp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31565 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31567 | rcode = to_string(v7, this_obj, &so, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31568 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31569 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31570 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31572 | if (v7_argc(v7) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31573 | rcode = v7_mk_regexp(v7, "", 0, "", 0, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31574 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31575 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31576 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31577 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31578 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31579 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31580 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31581 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31582 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31584 | if (!v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31585 | rcode = call_regex_ctor(v7, ro, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31586 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31587 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31588 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31589 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31591 | rxp = v7_get_regexp_struct(v7, ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31592 | flag_g = slre_get_flags(rxp->compiled_regexp) & SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31593 | if (!flag_g) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31594 | rcode = rx_exec(v7, ro, so, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31595 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31596 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31597 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31598 | rxp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31599 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31600 | while (lastMatch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31601 | val_t result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31603 | rcode = rx_exec(v7, ro, so, 1, &result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31604 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31605 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31606 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31607 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31608 | if (v7_is_null(result)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31609 | lastMatch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31610 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31611 | long thisIndex = rxp->lastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31612 | if (thisIndex == previousLastIndex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31613 | previousLastIndex = thisIndex + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31614 | rxp->lastIndex = previousLastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31615 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31616 | previousLastIndex = thisIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31617 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31618 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31619 | v7_array_push_throwing(v7, *res, v7_array_get(v7, result, 0), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31620 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31621 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31623 | n++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31624 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31625 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31627 | if (n == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31628 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31629 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31632 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31633 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31634 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31635 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31636 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31637 | V7_PRIVATE enum v7_err Str_replace(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31638 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31639 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31640 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31641 | size_t s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31642 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31643 | * Buffer of temporary strings returned by the replacement funciton. Will be |
Marko Mikulicic |
0:c0ecb8bf28eb | 31644 | * allocated below if only the replacement is a function. We need to store |
Marko Mikulicic |
0:c0ecb8bf28eb | 31645 | * each string in a separate `val_t`, because string data of length <= 5 is |
Marko Mikulicic |
0:c0ecb8bf28eb | 31646 | * stored right in `val_t`, so if there's more than one replacement, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31647 | * each subsequent replacement will overwrite the previous one. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31648 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31649 | val_t *tmp_str_buf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31650 | val_t out_str_o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31651 | char *old_owned_mbuf_base = v7->owned_strings.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31652 | char *old_owned_mbuf_end = v7->owned_strings.buf + v7->owned_strings.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31654 | rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31655 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31656 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31657 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31659 | s = v7_get_string(v7, &this_obj, &s_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31661 | if (s_len != 0 && v7_argc(v7) > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31662 | const char *const str_end = s + s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31663 | char *p = (char *) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31664 | uint32_t out_sub_num = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31665 | val_t ro = V7_UNDEFINED, str_func = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31666 | struct slre_prog *prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31667 | struct slre_cap out_sub[V7_RE_MAX_REPL_SUB], *ptok = out_sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31668 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31669 | int flag_g; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31671 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31672 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31673 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31674 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31675 | rcode = obj_value_of(v7, v7_arg(v7, 1), &str_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31676 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31677 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31678 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31680 | if (!v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31681 | rcode = call_regex_ctor(v7, ro, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31682 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31683 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31685 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31686 | prog = v7_get_regexp_struct(v7, ro)->compiled_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31687 | flag_g = slre_get_flags(prog) & SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31689 | if (!v7_is_callable(v7, str_func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31690 | rcode = to_string(v7, str_func, &str_func, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31691 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31692 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31693 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31694 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31696 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31697 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31698 | if (slre_exec(prog, 0, p, str_end, &loot)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31699 | if (p != loot.caps->start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31700 | ptok->start = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31701 | ptok->end = loot.caps->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31702 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31703 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31704 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31706 | if (v7_is_callable(v7, str_func)) { /* replace function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31707 | const char *rez_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31708 | size_t rez_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31709 | val_t arr = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31711 | for (i = 0; i < loot.num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31712 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 31713 | v7, arr, v7_mk_string(v7, loot.caps[i].start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31714 | loot.caps[i].end - loot.caps[i].start, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31715 | NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31716 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31717 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31718 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31719 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31720 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 31721 | v7, arr, v7_mk_number(v7, utfnlen(s, loot.caps[0].start - s)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31722 | NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31723 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31724 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31725 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31727 | rcode = v7_array_push_throwing(v7, arr, this_obj, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31728 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31729 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31732 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31733 | val_t val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31735 | rcode = b_apply(v7, str_func, this_obj, arr, 0, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31736 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31737 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31738 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31739 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31740 | if (tmp_str_buf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31741 | tmp_str_buf = (val_t *) calloc(sizeof(val_t), V7_RE_MAX_REPL_SUB); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31742 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31743 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31744 | rcode = to_string(v7, val, &tmp_str_buf[out_sub_num], NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31745 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31746 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31747 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31748 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31749 | rez_str = v7_get_string(v7, &tmp_str_buf[out_sub_num], &rez_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31750 | if (rez_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31751 | ptok->start = rez_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31752 | ptok->end = rez_str + rez_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31753 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31754 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31755 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31756 | } else { /* replace string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31757 | struct slre_loot newsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31758 | size_t f_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31759 | const char *f_str = v7_get_string(v7, &str_func, &f_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31760 | slre_replace(&loot, s, s_len, f_str, f_len, &newsub); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31761 | for (i = 0; i < newsub.num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31762 | ptok->start = newsub.caps[i].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31763 | ptok->end = newsub.caps[i].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31764 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31765 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31767 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31768 | p = (char *) loot.caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31769 | } while (flag_g && p < str_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31770 | if (p <= str_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31771 | ptok->start = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31772 | ptok->end = str_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31773 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31774 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31775 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31776 | out_str_o = v7_mk_string(v7, NULL, 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31777 | ptok = out_sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31778 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31779 | size_t ln = ptok->end - ptok->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31780 | const char *ps = ptok->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31781 | if (ptok->start >= old_owned_mbuf_base && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31782 | ptok->start < old_owned_mbuf_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31783 | ps += v7->owned_strings.buf - old_owned_mbuf_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31784 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31785 | out_str_o = s_concat(v7, out_str_o, v7_mk_string(v7, ps, ln, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31786 | p += ln; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31787 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31788 | } while (--out_sub_num); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31789 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31790 | *res = out_str_o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31791 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31792 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31794 | *res = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31796 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31797 | if (tmp_str_buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31798 | free(tmp_str_buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31799 | tmp_str_buf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31800 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31801 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31804 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31805 | V7_PRIVATE enum v7_err Str_search(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31806 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31807 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31808 | long utf_shift = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31810 | if (v7_argc(v7) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31811 | size_t s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31812 | struct slre_loot sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31813 | val_t so = V7_UNDEFINED, ro = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31814 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31816 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31817 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31818 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31819 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31821 | if (!v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31822 | rcode = call_regex_ctor(v7, ro, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31823 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31824 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31825 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31826 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31828 | rcode = to_string(v7, this_obj, &so, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31829 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31830 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31831 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31832 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31833 | s = v7_get_string(v7, &so, &s_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31835 | if (!slre_exec(v7_get_regexp_struct(v7, ro)->compiled_regexp, 0, s, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31836 | s + s_len, &sub)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31837 | utf_shift = utfnlen(s, sub.caps[0].start - s); /* calc shift for UTF-8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31838 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31839 | utf_shift = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31840 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31842 | *res = v7_mk_number(v7, utf_shift); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31843 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31844 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31845 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31848 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31850 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31851 | V7_PRIVATE enum v7_err Str_slice(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31852 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31853 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31854 | long from = 0, to = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31855 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31856 | val_t so = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31857 | const char *begin, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31858 | int num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31859 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31860 | rcode = to_string(v7, this_obj, &so, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31861 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31862 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31864 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31865 | begin = v7_get_string(v7, &so, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31867 | to = len = utfnlen(begin, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31868 | if (num_args > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31869 | rcode = to_long(v7, v7_arg(v7, 0), 0, &from); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31870 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31871 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31872 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31874 | if (from < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31875 | from += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31876 | if (from < 0) from = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31877 | } else if ((size_t) from > len) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31878 | from = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31879 | if (num_args > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31880 | rcode = to_long(v7, v7_arg(v7, 1), 0, &to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31881 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31882 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31883 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31885 | if (to < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31886 | to += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31887 | if (to < 0) to = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31888 | } else if ((size_t) to > len) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31889 | to = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31890 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31893 | if (from > to) to = from; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31894 | end = utfnshift(begin, to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31895 | begin = utfnshift(begin, from); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31897 | *res = v7_mk_string(v7, begin, end - begin, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31899 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31900 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31901 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31903 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31904 | static enum v7_err s_transform(struct v7 *v7, val_t obj, Rune (*func)(Rune), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31905 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31906 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31907 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31908 | size_t i, n, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31909 | const char *p2, *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31911 | rcode = to_string(v7, obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31912 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31913 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31914 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31916 | p = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31918 | /* Pass NULL to make sure we're not creating dictionary value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31919 | *res = v7_mk_string(v7, NULL, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31920 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31921 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31922 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31923 | p2 = v7_get_string(v7, res, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31924 | for (i = 0; i < len; i += n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31925 | n = chartorune(&r, p + i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31926 | r = func(r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31927 | runetochar((char *) p2 + i, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31928 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31929 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31931 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31932 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31933 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31935 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31936 | V7_PRIVATE enum v7_err Str_toLowerCase(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31937 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31938 | return s_transform(v7, this_obj, tolowerrune, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31939 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31941 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31942 | V7_PRIVATE enum v7_err Str_toUpperCase(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31943 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31944 | return s_transform(v7, this_obj, toupperrune, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31945 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31946 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31947 | static int s_isspace(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31948 | return isspacerune(c) || isnewline(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31949 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31950 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31951 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31952 | V7_PRIVATE enum v7_err Str_trim(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31953 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31954 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31955 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31956 | size_t i, n, len, start = 0, end, state = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31957 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31958 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31960 | rcode = to_string(v7, this_obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31961 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31962 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31963 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31964 | p = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31965 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31966 | end = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31967 | for (i = 0; i < len; i += n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31968 | n = chartorune(&r, p + i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31969 | if (!s_isspace(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31970 | if (state++ == 0) start = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31971 | end = i + n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31973 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31975 | *res = v7_mk_string(v7, p + start, end - start, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31976 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31977 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31978 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31979 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31981 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31982 | V7_PRIVATE enum v7_err Str_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31983 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31984 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31985 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31986 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31988 | rcode = obj_value_of(v7, this_obj, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31989 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31990 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31991 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31993 | if (v7_is_string(s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31994 | const char *p = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31995 | len = utfnlen(p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31996 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31998 | *res = v7_mk_number(v7, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31999 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32000 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32001 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32003 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32004 | V7_PRIVATE enum v7_err Str_at(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32005 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32006 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32007 | long arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32008 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32010 | rcode = to_long(v7, v7_arg(v7, 0), -1, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32011 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32012 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32013 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32015 | rcode = obj_value_of(v7, this_obj, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32016 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32017 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32020 | if (v7_is_string(s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32021 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32022 | const unsigned char *p = (unsigned char *) v7_get_string(v7, &s, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32023 | if (arg0 >= 0 && (size_t) arg0 < n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32024 | *res = v7_mk_number(v7, p[arg0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32025 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32027 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32029 | *res = v7_mk_number(v7, NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32031 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32032 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32033 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32035 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32036 | V7_PRIVATE enum v7_err Str_blen(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32037 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32038 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32039 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32040 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32042 | rcode = obj_value_of(v7, this_obj, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32043 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32044 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32045 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32046 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32047 | if (v7_is_string(s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32048 | v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32049 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32051 | *res = v7_mk_number(v7, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32053 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32054 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32055 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32057 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32058 | static enum v7_err s_substr(struct v7 *v7, val_t s, long start, long len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32059 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32060 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32061 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32062 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32064 | rcode = to_string(v7, s, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32065 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32066 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32069 | p = v7_get_string(v7, &s, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32070 | n = utfnlen(p, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32072 | if (start < (long) n && len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32073 | if (start < 0) start = (long) n + start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32074 | if (start < 0) start = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32076 | if (start > (long) n) start = n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32077 | if (len < 0) len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32078 | if (len > (long) n - start) len = n - start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32079 | p = utfnshift(p, start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32080 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32081 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32082 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32084 | *res = v7_mk_string(v7, p, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32085 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32086 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32087 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32089 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32090 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32091 | V7_PRIVATE enum v7_err Str_substr(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32092 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32093 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32094 | long start, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32095 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32096 | rcode = to_long(v7, v7_arg(v7, 0), 0, &start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32097 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32098 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32099 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32100 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32101 | rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32102 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32103 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32104 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32106 | rcode = s_substr(v7, this_obj, start, len, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32107 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32108 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32109 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32110 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32111 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32112 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32113 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32115 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32116 | V7_PRIVATE enum v7_err Str_substring(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32117 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32118 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32119 | long start, end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32121 | rcode = to_long(v7, v7_arg(v7, 0), 0, &start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32122 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32123 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32124 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32125 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32126 | rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32127 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32128 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32129 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32131 | if (start < 0) start = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32132 | if (end < 0) end = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32133 | if (start > end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32134 | long tmp = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32135 | start = end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32136 | end = tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32137 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32139 | rcode = s_substr(v7, this_obj, start, end - start, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32140 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32142 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32143 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32144 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32146 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32147 | V7_PRIVATE enum v7_err Str_split(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32148 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32149 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32150 | const char *s, *s_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32151 | size_t s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32152 | long num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32153 | rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32154 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32155 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32156 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32157 | s = v7_get_string(v7, &this_obj, &s_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32158 | s_end = s + s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32160 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32162 | if (num_args == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32163 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32164 | * No arguments were given: resulting array will contain just a single |
Marko Mikulicic |
0:c0ecb8bf28eb | 32165 | * element: the source string |
Marko Mikulicic |
0:c0ecb8bf28eb | 32166 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32167 | rcode = v7_array_push_throwing(v7, *res, this_obj, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32168 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32169 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32170 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32171 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32172 | val_t ro = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32173 | long elem, limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32174 | size_t lookup_idx = 0, substr_idx = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32175 | struct _str_split_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32177 | rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32178 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32179 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32180 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32182 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32183 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32184 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32185 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32187 | /* Initialize substring context depending on the argument type */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32188 | if (v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32189 | /* use RegExp implementation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32190 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32191 | ctx.p_init = subs_regexp_init; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32192 | ctx.p_exec = subs_regexp_exec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32193 | ctx.p_add_caps = subs_regexp_split_add_caps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32194 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 32195 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32196 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32197 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32198 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32199 | * use String implementation: first of all, convert to String (if it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 32200 | * not already a String) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32201 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32202 | rcode = to_string(v7, ro, &ro, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32203 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32204 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32205 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32207 | ctx.p_init = subs_string_init; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32208 | ctx.p_exec = subs_string_exec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32209 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32210 | ctx.p_add_caps = subs_string_split_add_caps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32211 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32212 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32213 | /* initialize context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32214 | ctx.p_init(&ctx, v7, ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32216 | if (s_len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32217 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32218 | * if `this` is (or converts to) an empty string, resulting array should |
Marko Mikulicic |
0:c0ecb8bf28eb | 32219 | * contain empty string if only separator does not match an empty string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 32220 | * Otherwise, the array is left empty |
Marko Mikulicic |
0:c0ecb8bf28eb | 32221 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32222 | int matches_empty = !ctx.p_exec(&ctx, s, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32223 | if (!matches_empty) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32224 | rcode = v7_array_push_throwing(v7, *res, this_obj, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32225 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32226 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32227 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32228 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32229 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32230 | size_t last_match_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32232 | for (elem = 0; elem < limit && lookup_idx < s_len;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32233 | size_t substr_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32234 | /* find next match, and break if there's no match */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32235 | if (ctx.p_exec(&ctx, s + lookup_idx, s_end)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32237 | last_match_len = ctx.match_end - ctx.match_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32238 | substr_len = ctx.match_start - s - substr_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32239 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32240 | /* add next substring to the resulting array, if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32241 | if (substr_len > 0 || last_match_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32242 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 32243 | v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32244 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32245 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32246 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32247 | elem++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32249 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32250 | /* Add captures (for RegExp only) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32251 | elem = ctx.p_add_caps(&ctx, *res, elem, limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32252 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32253 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32255 | /* advance lookup_idx appropriately */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32256 | if (last_match_len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32257 | /* empty match: advance to the next char */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32258 | const char *next = utfnshift((s + lookup_idx), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32259 | lookup_idx += (next - (s + lookup_idx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32260 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32261 | /* non-empty match: advance to the end of match */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32262 | lookup_idx = ctx.match_end - s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32263 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32264 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32265 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32266 | * always remember the end of the match, so that next time we will take |
Marko Mikulicic |
0:c0ecb8bf28eb | 32267 | * substring from that position |
Marko Mikulicic |
0:c0ecb8bf28eb | 32268 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32269 | substr_idx = ctx.match_end - s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32270 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32272 | /* add the last substring to the resulting array, if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32273 | if (elem < limit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32274 | size_t substr_len = s_len - substr_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32275 | if (substr_len > 0 || last_match_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32276 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 32277 | v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32278 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32279 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32280 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32281 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32282 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32283 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32284 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32286 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32287 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32288 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32290 | V7_PRIVATE void init_string(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32291 | val_t str = mk_cfunction_obj_with_proto(v7, String_ctor, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32292 | v7->vals.string_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32293 | v7_def(v7, v7->vals.global_object, "String", 6, V7_DESC_ENUMERABLE(0), str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32295 | set_cfunc_prop(v7, str, "fromCharCode", Str_fromCharCode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32296 | set_cfunc_prop(v7, v7->vals.string_prototype, "charCodeAt", Str_charCodeAt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32297 | set_cfunc_prop(v7, v7->vals.string_prototype, "charAt", Str_charAt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32298 | set_cfunc_prop(v7, v7->vals.string_prototype, "concat", Str_concat); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32299 | set_cfunc_prop(v7, v7->vals.string_prototype, "indexOf", Str_indexOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32300 | set_cfunc_prop(v7, v7->vals.string_prototype, "substr", Str_substr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32301 | set_cfunc_prop(v7, v7->vals.string_prototype, "substring", Str_substring); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32302 | set_cfunc_prop(v7, v7->vals.string_prototype, "valueOf", Str_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32303 | set_cfunc_prop(v7, v7->vals.string_prototype, "lastIndexOf", Str_lastIndexOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32304 | #if V7_ENABLE__String__localeCompare |
Marko Mikulicic |
0:c0ecb8bf28eb | 32305 | set_cfunc_prop(v7, v7->vals.string_prototype, "localeCompare", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32306 | Str_localeCompare); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32307 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32308 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32309 | set_cfunc_prop(v7, v7->vals.string_prototype, "match", Str_match); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32310 | set_cfunc_prop(v7, v7->vals.string_prototype, "replace", Str_replace); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32311 | set_cfunc_prop(v7, v7->vals.string_prototype, "search", Str_search); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32312 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32313 | set_cfunc_prop(v7, v7->vals.string_prototype, "split", Str_split); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32314 | set_cfunc_prop(v7, v7->vals.string_prototype, "slice", Str_slice); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32315 | set_cfunc_prop(v7, v7->vals.string_prototype, "trim", Str_trim); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32316 | set_cfunc_prop(v7, v7->vals.string_prototype, "toLowerCase", Str_toLowerCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32317 | #if V7_ENABLE__String__localeLowerCase |
Marko Mikulicic |
0:c0ecb8bf28eb | 32318 | set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleLowerCase", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32319 | Str_toLowerCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32320 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32321 | set_cfunc_prop(v7, v7->vals.string_prototype, "toUpperCase", Str_toUpperCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32322 | #if V7_ENABLE__String__localeUpperCase |
Marko Mikulicic |
0:c0ecb8bf28eb | 32323 | set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleUpperCase", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32324 | Str_toUpperCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32325 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32326 | set_cfunc_prop(v7, v7->vals.string_prototype, "toString", Str_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32328 | v7_def(v7, v7->vals.string_prototype, "length", 6, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32329 | v7_mk_cfunction(Str_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32331 | /* Non-standard Cesanta extension */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32332 | set_cfunc_prop(v7, v7->vals.string_prototype, "at", Str_at); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32333 | v7_def(v7, v7->vals.string_prototype, "blen", 4, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32334 | v7_mk_cfunction(Str_blen)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32335 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32336 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 32337 | #line 1 "v7/src/std_date.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 32338 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32339 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32340 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 32341 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 32342 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32344 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32345 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32346 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32347 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32348 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32349 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32350 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32351 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32352 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32353 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32354 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32356 | #if V7_ENABLE__Date |
Marko Mikulicic |
0:c0ecb8bf28eb | 32357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32358 | #include <locale.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 32359 | #include <time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 32360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32361 | #ifndef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32362 | extern long timezone; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32363 | #include <sys/time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 32364 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32366 | #if defined(_MSC_VER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32367 | #define timezone _timezone |
Marko Mikulicic |
0:c0ecb8bf28eb | 32368 | #define tzname _tzname |
Marko Mikulicic |
0:c0ecb8bf28eb | 32369 | #if _MSC_VER >= 1800 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32370 | #define tzset _tzset |
Marko Mikulicic |
0:c0ecb8bf28eb | 32371 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32372 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32374 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32375 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32376 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32378 | typedef double etime_t; /* double is suitable type for ECMA time */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32379 | /* inernally we have to use 64-bit integer for some operations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32380 | typedef int64_t etimeint_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32381 | #define INVALID_TIME NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 32382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32383 | #define msPerDay 86400000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32384 | #define HoursPerDay 24 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32385 | #define MinutesPerHour 60 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32386 | #define SecondsPerMinute 60 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32387 | #define SecondsPerHour 3600 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32388 | #define msPerSecond 1000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32389 | #define msPerMinute 60000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32390 | #define msPerHour 3600000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32391 | #define MonthsInYear 12 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32393 | /* ECMA alternative to struct tm */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32394 | struct timeparts { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32395 | int year; /* can be negative, up to +-282000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32396 | int month; /* 0-11 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32397 | int day; /* 1-31 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32398 | int hour; /* 0-23 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32399 | int min; /* 0-59 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32400 | int sec; /* 0-59 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32401 | int msec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32402 | int dayofweek; /* 0-6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32403 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32405 | static etimeint_t g_gmtoffms; /* timezone offset, ms, no DST */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32406 | static const char *g_tzname; /* current timezone name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32408 | /* Leap year formula copied from ECMA 5.1 standart as is */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32409 | static int ecma_DaysInYear(int y) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32410 | if (y % 4 != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32411 | return 365; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32412 | } else if (y % 4 == 0 && y % 100 != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32413 | return 366; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32414 | } else if (y % 100 == 0 && y % 400 != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32415 | return 365; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32416 | } else if (y % 400 == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32417 | return 366; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32418 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32419 | return 365; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32420 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32421 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32422 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32423 | static etimeint_t ecma_DayFromYear(etimeint_t y) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32424 | return 365 * (y - 1970) + floor((y - 1969) / 4) - floor((y - 1901) / 100) + |
Marko Mikulicic |
0:c0ecb8bf28eb | 32425 | floor((y - 1601) / 400); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32428 | static etimeint_t ecma_TimeFromYear(etimeint_t y) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32429 | return msPerDay * ecma_DayFromYear(y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32430 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32432 | static int ecma_IsLeapYear(int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32433 | return ecma_DaysInYear(year) == 366; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32434 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32436 | static int *ecma_getfirstdays(int isleap) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32437 | static int sdays[2][MonthsInYear + 1] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32438 | {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32439 | {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32441 | return sdays[isleap]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32442 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32443 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32444 | static int ecma_DaylightSavingTA(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32445 | time_t time = t / 1000; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32446 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32447 | * Win32 doesn't have locatime_r |
Marko Mikulicic |
0:c0ecb8bf28eb | 32448 | * nixes don't have localtime_s |
Marko Mikulicic |
0:c0ecb8bf28eb | 32449 | * as result using localtime |
Marko Mikulicic |
0:c0ecb8bf28eb | 32450 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32451 | struct tm *tm = localtime(&time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32452 | if (tm == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32453 | /* doesn't work on windows for times before epoch */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32454 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32455 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32456 | if (tm->tm_isdst > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32457 | return msPerHour; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32458 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32459 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32463 | static int ecma_LocalTZA(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32464 | return (int) -g_gmtoffms; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32465 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32467 | static etimeint_t ecma_UTC(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32468 | return t - ecma_LocalTZA() - ecma_DaylightSavingTA(t - ecma_LocalTZA()); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32469 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32471 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32472 | V7_ENABLE__Date__toJSON || V7_ENABLE__Date__getters || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32473 | V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 32474 | static int ecma_YearFromTime_s(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32475 | int first = floor((t / msPerDay) / 366) + 1970, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32476 | last = floor((t / msPerDay) / 365) + 1970, middle = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32478 | if (last < first) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32479 | int temp = first; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32480 | first = last; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32481 | last = temp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32482 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32484 | while (last > first) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32485 | middle = (last + first) / 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32486 | if (ecma_TimeFromYear(middle) > t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32487 | last = middle - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32488 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32489 | if (ecma_TimeFromYear(middle) <= t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32490 | if (ecma_TimeFromYear(middle + 1) > t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32491 | first = middle; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32492 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32493 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32494 | first = middle + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32495 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32496 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32499 | return first; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32500 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32502 | static etimeint_t ecma_Day(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32503 | return floor(t / msPerDay); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32504 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32506 | static int ecma_DayWithinYear(etime_t t, int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32507 | return (int) (ecma_Day(t) - ecma_DayFromYear(year)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32508 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32510 | static int ecma_MonthFromTime(etime_t t, int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32511 | int *days, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32512 | etimeint_t dwy = ecma_DayWithinYear(t, year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32513 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32514 | days = ecma_getfirstdays(ecma_IsLeapYear(year)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32515 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32516 | for (i = 0; i < MonthsInYear; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32517 | if (dwy >= days[i] && dwy < days[i + 1]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32518 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32519 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32520 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32521 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32522 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32525 | static int ecma_DateFromTime(etime_t t, int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32526 | int *days, mft = ecma_MonthFromTime(t, year), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32527 | dwy = ecma_DayWithinYear(t, year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32529 | if (mft > 11) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32530 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32531 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32533 | days = ecma_getfirstdays(ecma_IsLeapYear(year)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32535 | return dwy - days[mft] + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32536 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32538 | #define DEF_EXTRACT_TIMEPART(funcname, c1, c2) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32539 | static int ecma_##funcname(etime_t t) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32540 | int ret = (etimeint_t) floor(t / c1) % c2; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32541 | if (ret < 0) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32542 | ret += c2; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32543 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32544 | return ret; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32545 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32546 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32547 | DEF_EXTRACT_TIMEPART(HourFromTime, msPerHour, HoursPerDay) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32548 | DEF_EXTRACT_TIMEPART(MinFromTime, msPerMinute, MinutesPerHour) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32549 | DEF_EXTRACT_TIMEPART(SecFromTime, msPerSecond, SecondsPerMinute) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32550 | DEF_EXTRACT_TIMEPART(msFromTime, 1, msPerSecond) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32552 | static int ecma_WeekDay(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32553 | int ret = (ecma_Day(t) + 4) % 7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32554 | if (ret < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32555 | ret += 7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32556 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32557 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32558 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32559 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32561 | static void d_gmtime(const etime_t *t, struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32562 | tp->year = ecma_YearFromTime_s(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32563 | tp->month = ecma_MonthFromTime(*t, tp->year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32564 | tp->day = ecma_DateFromTime(*t, tp->year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32565 | tp->hour = ecma_HourFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32566 | tp->min = ecma_MinFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32567 | tp->sec = ecma_SecFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32568 | tp->msec = ecma_msFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32569 | tp->dayofweek = ecma_WeekDay(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32570 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32571 | #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32572 | V7_ENABLE__Date__getters || V7_ENABLE__Date__setters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32574 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32575 | V7_ENABLE__Date__getters || V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 32576 | static etimeint_t ecma_LocalTime(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32577 | return t + ecma_LocalTZA() + ecma_DaylightSavingTA(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32578 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32580 | static void d_localtime(const etime_t *time, struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32581 | etime_t local_time = ecma_LocalTime(*time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32582 | d_gmtime(&local_time, tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32583 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32584 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32586 | static etimeint_t ecma_MakeTime(etimeint_t hour, etimeint_t min, etimeint_t sec, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32587 | etimeint_t ms) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32588 | return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * |
Marko Mikulicic |
0:c0ecb8bf28eb | 32589 | msPerSecond + |
Marko Mikulicic |
0:c0ecb8bf28eb | 32590 | ms; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32593 | static etimeint_t ecma_MakeDay(int year, int month, int date) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32594 | int *days; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32595 | etimeint_t yday, mday; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32597 | year += floor(month / 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32598 | month = month % 12; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32599 | yday = floor(ecma_TimeFromYear(year) / msPerDay); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32600 | days = ecma_getfirstdays(ecma_IsLeapYear(year)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32601 | mday = days[month]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32603 | return yday + mday + date - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32604 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32605 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32606 | static etimeint_t ecma_MakeDate(etimeint_t day, etimeint_t time) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32607 | return (day * msPerDay + time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32608 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32610 | static void d_gettime(etime_t *t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32611 | #ifndef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32612 | struct timeval tv; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32613 | gettimeofday(&tv, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32614 | *t = (etime_t) tv.tv_sec * 1000 + (etime_t) tv.tv_usec / 1000; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32615 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 32616 | /* TODO(mkm): use native windows API in order to get ms granularity */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32617 | *t = time(NULL) * 1000.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32618 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32619 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32621 | static etime_t d_mktime_impl(const struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32622 | return ecma_MakeDate(ecma_MakeDay(tp->year, tp->month, tp->day), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32623 | ecma_MakeTime(tp->hour, tp->min, tp->sec, tp->msec)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32624 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32626 | #if V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 32627 | static etime_t d_lmktime(const struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32628 | return ecma_UTC(d_mktime_impl(tp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32629 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32630 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32632 | static etime_t d_gmktime(const struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32633 | return d_mktime_impl(tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32634 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32635 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32636 | typedef etime_t (*fmaketime_t)(const struct timeparts *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32637 | typedef void (*fbreaktime_t)(const etime_t *, struct timeparts *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32638 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32639 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32640 | V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 32641 | static val_t d_trytogetobjforstring(struct v7 *v7, val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32642 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32643 | val_t ret = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32645 | rcode = obj_value_of(v7, obj, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32646 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32647 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32648 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32649 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32650 | if (ret == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32651 | rcode = v7_throwf(v7, TYPE_ERROR, "Date is invalid (for string)"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32652 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32653 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32655 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32656 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32657 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32658 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32659 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32661 | #if V7_ENABLE__Date__parse || V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 32662 | static int d_iscalledasfunction(struct v7 *v7, val_t this_obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32663 | /* TODO(alashkin): verify this statement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32664 | return is_prototype_of(v7, this_obj, v7->vals.date_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32665 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32666 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32668 | static const char *mon_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32669 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32671 | int d_getnumbyname(const char **arr, int arr_size, const char *str) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32672 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32673 | for (i = 0; i < arr_size; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32674 | if (strncmp(arr[i], str, 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32675 | return i + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32679 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32680 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32682 | int date_parse(const char *str, int *a1, int *a2, int *a3, char sep, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32683 | char *rest) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32684 | char frmDate[] = " %d/%d/%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32685 | frmDate[3] = frmDate[6] = sep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32686 | return sscanf(str, frmDate, a1, a2, a3, rest); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32687 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32689 | #define NO_TZ 0x7FFFFFFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 32690 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32691 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32692 | * not very smart but simple, and working according |
Marko Mikulicic |
0:c0ecb8bf28eb | 32693 | * to ECMA5.1 StringToDate function |
Marko Mikulicic |
0:c0ecb8bf28eb | 32694 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32695 | static int d_parsedatestr(const char *jstr, size_t len, struct timeparts *tp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32696 | int *tz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32697 | char gmt[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32698 | char buf1[100] = {0}, buf2[100] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32699 | int res = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32700 | char str[101]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32701 | memcpy(str, jstr, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32702 | str[len] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32703 | memset(tp, 0, sizeof(*tp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32704 | *tz = NO_TZ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32706 | /* trying toISOSrting() format */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32707 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32708 | const char *frmISOString = " %d-%02d-%02dT%02d:%02d:%02d.%03dZ"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32709 | res = sscanf(str, frmISOString, &tp->year, &tp->month, &tp->day, &tp->hour, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32710 | &tp->min, &tp->sec, &tp->msec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32711 | if (res == 7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32712 | *tz = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32713 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32714 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32715 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32716 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32717 | /* trying toString()/toUTCString()/toDateFormat() formats */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32718 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32719 | char month[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32720 | int dowlen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32721 | const char *frmString = " %*s%n %03s %02d %d %02d:%02d:%02d %03s%d"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32722 | res = sscanf(str, frmString, &dowlen, month, &tp->day, &tp->year, &tp->hour, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32723 | &tp->min, &tp->sec, gmt, tz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32724 | if ((res == 3 || (res >= 6 && res <= 8)) && dowlen == 3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32725 | if ((tp->month = d_getnumbyname(mon_name, ARRAY_SIZE(mon_name), month)) != |
Marko Mikulicic |
0:c0ecb8bf28eb | 32726 | -1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32727 | if (res == 7 && strncmp(gmt, "GMT", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32728 | *tz = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32729 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32730 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32731 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32732 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32733 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32735 | /* trying the rest */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32736 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32737 | /* trying date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32739 | if (!(date_parse(str, &tp->month, &tp->day, &tp->year, '/', buf1) >= 3 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 32740 | date_parse(str, &tp->day, &tp->month, &tp->year, '.', buf1) >= 3 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 32741 | date_parse(str, &tp->year, &tp->month, &tp->day, '-', buf1) >= 3)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32742 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32743 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32745 | /* there is date, trying time; from here return 0 only on errors */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32746 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32747 | /* trying HH:mm */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32748 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32749 | const char *frmMMhh = " %d:%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32750 | res = sscanf(buf1, frmMMhh, &tp->hour, &tp->min, buf2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32751 | /* can't get time, but have some symbols, assuming error */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32752 | if (res < 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32753 | return (strlen(buf2) == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32754 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32755 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32756 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32757 | /* trying seconds */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32758 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32759 | const char *frmss = ":%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32760 | memset(buf1, 0, sizeof(buf1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32761 | res = sscanf(buf2, frmss, &tp->sec, buf1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32762 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32764 | /* even if we don't get seconds we gonna try to get tz */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32765 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32766 | char *rest = res ? buf1 : buf2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32767 | char *buf = res ? buf2 : buf1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32768 | const char *frmtz = " %03s%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32770 | res = sscanf(rest, frmtz, gmt, tz, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32771 | if (res == 1 && strncmp(gmt, "GMT", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32772 | *tz = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32773 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32774 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32775 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32776 | /* return OK if we are at the end of string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32777 | return res <= 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32778 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32780 | static int d_timeFromString(etime_t *time, const char *str, size_t str_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32781 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32782 | int tz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32784 | *time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32786 | if (str_len > 100) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32787 | /* too long for valid date string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32788 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32789 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32790 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32791 | if (d_parsedatestr(str, str_len, &tp, &tz)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32792 | /* check results */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32793 | int valid = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32794 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32795 | tp.month--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32796 | valid = tp.day >= 1 && tp.day <= 31; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32797 | valid &= tp.month >= 0 && tp.month <= 11; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32798 | valid &= tp.hour >= 0 && tp.hour <= 23; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32799 | valid &= tp.min >= 0 && tp.min <= 59; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32800 | valid &= tp.sec >= 0 && tp.sec <= 59; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32802 | if (tz != NO_TZ && tz > 12) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32803 | tz /= 100; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32804 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32805 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32806 | valid &= (abs(tz) <= 12 || tz == NO_TZ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32808 | if (valid) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32809 | *time = d_gmktime(&tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32811 | if (tz != NO_TZ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32812 | /* timezone specified, use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32813 | *time -= (tz * msPerHour); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32814 | } else if (tz != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32815 | /* assuming local timezone and moving back to UTC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32816 | *time = ecma_UTC(*time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32817 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32818 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32819 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32821 | return !isnan(*time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32822 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32824 | /* notice: holding month in calendar format (1-12, not 0-11) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32825 | struct dtimepartsarr { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32826 | etime_t args[7]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32827 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32829 | enum detimepartsarr { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32830 | tpyear = 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32831 | tpmonth, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32832 | tpdate, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32833 | tphours, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32834 | tpminutes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32835 | tpseconds, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32836 | tpmsec, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32837 | tpmax |
Marko Mikulicic |
0:c0ecb8bf28eb | 32838 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32840 | static etime_t d_changepartoftime(const etime_t *current, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32841 | struct dtimepartsarr *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32842 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32843 | fmaketime_t maketimefunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32844 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32845 | * 0 = year, 1 = month , 2 = date , 3 = hours, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32846 | * 4 = minutes, 5 = seconds, 6 = ms |
Marko Mikulicic |
0:c0ecb8bf28eb | 32847 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32848 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32849 | unsigned long i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32850 | int *tp_arr[7]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32851 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32852 | * C89 doesn't allow initialization |
Marko Mikulicic |
0:c0ecb8bf28eb | 32853 | * like x = {&tp.year, &tp.month, .... } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32854 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32855 | tp_arr[0] = &tp.year; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32856 | tp_arr[1] = &tp.month; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32857 | tp_arr[2] = &tp.day; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32858 | tp_arr[3] = &tp.hour; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32859 | tp_arr[4] = &tp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32860 | tp_arr[5] = &tp.sec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32861 | tp_arr[6] = &tp.msec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32863 | memset(&tp, 0, sizeof(tp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32864 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32865 | if (breaktimefunc != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32866 | breaktimefunc(current, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32867 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32869 | for (i = 0; i < ARRAY_SIZE(tp_arr); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32870 | if (!isnan(a->args[i]) && !isinf(a->args[i])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32871 | *tp_arr[i] = (int) a->args[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32872 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32873 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32875 | return maketimefunc(&tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32876 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32878 | #if V7_ENABLE__Date__setters || V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 32879 | static etime_t d_time_number_from_arr(struct v7 *v7, int start_pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32880 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32881 | fmaketime_t maketimefunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32882 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32883 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32884 | etime_t ret_time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32885 | long cargs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32887 | val_t objtime = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32888 | rcode = obj_value_of(v7, this_obj, &objtime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32889 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32890 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32893 | if ((cargs = v7_argc(v7)) >= 1 && objtime != V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32894 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32895 | etime_t new_part = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32896 | struct dtimepartsarr a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32897 | for (i = 0; i < 7; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32898 | a.args[i] = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32899 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32901 | for (i = 0; i < cargs && (i + start_pos < tpmax); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32902 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32903 | val_t arg = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32904 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32905 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32906 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32907 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32908 | new_part = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32909 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32911 | if (isnan(new_part)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32912 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32913 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32915 | a.args[i + start_pos] = new_part; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32916 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32918 | if (!isnan(new_part)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32919 | etime_t current_time = v7_get_double(v7, objtime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32920 | ret_time = |
Marko Mikulicic |
0:c0ecb8bf28eb | 32921 | d_changepartoftime(¤t_time, &a, breaktimefunc, maketimefunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32923 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32925 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32926 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32927 | return ret_time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32928 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32929 | #endif /* V7_ENABLE__Date__setters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32931 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 32932 | static int d_tptostr(const struct timeparts *tp, char *buf, int addtz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32933 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32935 | /* constructor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32936 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32937 | V7_PRIVATE enum v7_err Date_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32938 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32939 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32940 | etime_t ret_time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32941 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32942 | long cargs = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32943 | if (cargs <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32944 | /* no parameters - return current date & time */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32945 | d_gettime(&ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32946 | } else if (cargs == 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32947 | /* one parameter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32948 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32949 | if (v7_is_string(arg)) { /* it could be string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32950 | size_t str_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32951 | const char *str = v7_get_string(v7, &arg, &str_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32952 | d_timeFromString(&ret_time, str, str_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32953 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32954 | if (isnan(ret_time)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32955 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32956 | * if cannot be parsed or |
Marko Mikulicic |
0:c0ecb8bf28eb | 32957 | * not string at all - trying to convert to number |
Marko Mikulicic |
0:c0ecb8bf28eb | 32958 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32959 | ret_time = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32960 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32961 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32962 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32963 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32964 | ret_time = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32965 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32966 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32967 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32968 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32969 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32970 | /* 2+ paramaters - should be parts of a date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32971 | struct dtimepartsarr a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32972 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32974 | memset(&a, 0, sizeof(a)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32975 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32976 | for (i = 0; i < cargs; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32977 | val_t arg = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32978 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32979 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32980 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32982 | a.args[i] = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32983 | if (isnan(a.args[i])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32984 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32985 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32986 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32988 | if (i >= cargs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32989 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32990 | * If date is supplied then let |
Marko Mikulicic |
0:c0ecb8bf28eb | 32991 | * dt be ToNumber(date); else let dt be 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 32992 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32993 | if (a.args[tpdate] == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32994 | a.args[tpdate] = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32995 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32996 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32997 | if (a.args[tpyear] >= 0 && a.args[tpyear] <= 99) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32998 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32999 | * If y is not NaN and 0 <= ToInteger(y) <= 99, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33000 | * then let yr be 1900+ToInteger(y); otherwise, let yr be y. |
Marko Mikulicic |
0:c0ecb8bf28eb | 33001 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33002 | a.args[tpyear] += 1900; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33003 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33005 | ret_time = ecma_UTC(d_changepartoftime(0, &a, 0, d_gmktime)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33009 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33010 | get_object_struct(v7->vals.date_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33012 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_number(v7, ret_time)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33013 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33014 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 33015 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 33016 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33017 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33018 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33019 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33020 | * according to 15.9.2.1 we should ignore all |
Marko Mikulicic |
0:c0ecb8bf28eb | 33021 | * parameters in case of function-call |
Marko Mikulicic |
0:c0ecb8bf28eb | 33022 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33023 | char buf[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33024 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33026 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33027 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33028 | d_gettime(&ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33029 | d_localtime(&ret_time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33030 | len = d_tptostr(&tp, buf, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33031 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 33032 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33033 | #endif /* V7_ENABLE__Date__toString */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33035 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33036 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33039 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33040 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33041 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33042 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33043 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 33044 | static int d_timetoISOstr(const etime_t *time, char *buf, size_t buf_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33045 | /* ISO format: "+XXYYYY-MM-DDTHH:mm:ss.sssZ"; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33046 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33047 | char use_ext = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33048 | const char *ey_frm = "%06d-%02d-%02dT%02d:%02d:%02d.%03dZ"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33049 | const char *simpl_frm = "%d-%02d-%02dT%02d:%02d:%02d.%03dZ"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33051 | d_gmtime(time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33053 | if (abs(tp.year) > 9999 || tp.year < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33054 | *buf = (tp.year > 0) ? '+' : '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33055 | use_ext = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33056 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33058 | return c_snprintf(buf + use_ext, buf_size - use_ext, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33059 | use_ext ? ey_frm : simpl_frm, abs(tp.year), tp.month + 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33060 | tp.day, tp.hour, tp.min, tp.sec, tp.msec) + |
Marko Mikulicic |
0:c0ecb8bf28eb | 33061 | use_ext; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33062 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33064 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33065 | V7_PRIVATE enum v7_err Date_toISOString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33066 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33067 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33068 | char buf[30]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33069 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33070 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33072 | if (val_type(v7, this_obj) != V7_TYPE_DATE_OBJECT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33073 | rcode = v7_throwf(v7, TYPE_ERROR, "This is not a Date object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33074 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33075 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33076 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33077 | time = v7_get_double(v7, d_trytogetobjforstring(v7, this_obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33078 | len = d_timetoISOstr(&time, buf, sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33079 | if (len > (int) (sizeof(buf) - 1 /*null-term*/)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33080 | len = (int) (sizeof(buf) - 1 /*null-term*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33083 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33085 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33086 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33087 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33088 | #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33089 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33090 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33091 | typedef int (*ftostring_t)(const struct timeparts *, char *, int); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33092 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33093 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33094 | static enum v7_err d_tostring(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33095 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33096 | ftostring_t tostringfunc, int addtz, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33097 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33098 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33099 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33100 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33101 | char buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33102 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33104 | time = v7_get_double(v7, d_trytogetobjforstring(v7, obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33106 | breaktimefunc(&time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33107 | len = tostringfunc(&tp, buf, addtz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33109 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33110 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33113 | /* using macros to avoid copy-paste technic */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33114 | #define DEF_TOSTR(funcname, breaktimefunc, tostrfunc, addtz) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33115 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33116 | V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33117 | val_t this_obj = v7_get_this(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33118 | return d_tostring(v7, this_obj, breaktimefunc, tostrfunc, addtz, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33121 | /* non-locale function should always return in english and 24h-format */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33122 | static const char *wday_name[] = {"Sun", "Mon", "Tue", "Wed", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33123 | "Thu", "Fri", "Sat"}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33125 | static int d_tptodatestr(const struct timeparts *tp, char *buf, int addtz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33126 | (void) addtz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33128 | return sprintf(buf, "%s %s %02d %d", wday_name[tp->dayofweek], |
Marko Mikulicic |
0:c0ecb8bf28eb | 33129 | mon_name[tp->month], tp->day, tp->year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33130 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33132 | DEF_TOSTR(DateString, d_localtime, d_tptodatestr, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33134 | static const char *d_gettzname(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33135 | return g_tzname; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33136 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33138 | static int d_tptotimestr(const struct timeparts *tp, char *buf, int addtz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33139 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33141 | len = sprintf(buf, "%02d:%02d:%02d GMT", tp->hour, tp->min, tp->sec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33143 | if (addtz && g_gmtoffms != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33144 | len = sprintf(buf + len, "%c%02d00 (%s)", g_gmtoffms > 0 ? '-' : '+', |
Marko Mikulicic |
0:c0ecb8bf28eb | 33145 | abs((int) g_gmtoffms / msPerHour), d_gettzname()); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33146 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33147 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33148 | return (int) strlen(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33149 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33151 | DEF_TOSTR(TimeString, d_localtime, d_tptotimestr, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33153 | static int d_tptostr(const struct timeparts *tp, char *buf, int addtz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33154 | int len = d_tptodatestr(tp, buf, addtz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33155 | *(buf + len) = ' '; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33156 | return d_tptotimestr(tp, buf + len + 1, addtz) + len + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33157 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33159 | DEF_TOSTR(String, d_localtime, d_tptostr, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33160 | DEF_TOSTR(UTCString, d_gmtime, d_tptostr, 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33161 | #endif /* V7_ENABLE__Date__toString */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33162 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33163 | #if V7_ENABLE__Date__toLocaleString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33164 | struct d_locale { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33165 | char locale[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33166 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33167 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33168 | static void d_getcurrentlocale(struct d_locale *loc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33169 | strcpy(loc->locale, setlocale(LC_TIME, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33170 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33172 | static void d_setlocale(const struct d_locale *loc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33173 | setlocale(LC_TIME, loc ? loc->locale : ""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33174 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33175 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33176 | /* TODO(alashkin): check portability */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33177 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33178 | static enum v7_err d_tolocalestr(struct v7 *v7, val_t obj, const char *frm, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33179 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33180 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33181 | char buf[250]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33182 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33183 | struct tm t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33184 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33185 | struct d_locale prev_locale; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33186 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33187 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33188 | time = v7_get_double(v7, d_trytogetobjforstring(v7, obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33189 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33190 | d_getcurrentlocale(&prev_locale); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33191 | d_setlocale(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33192 | d_localtime(&time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33194 | memset(&t, 0, sizeof(t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33195 | t.tm_year = tp.year - 1900; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33196 | t.tm_mon = tp.month; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33197 | t.tm_mday = tp.day; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33198 | t.tm_hour = tp.hour; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33199 | t.tm_min = tp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33200 | t.tm_sec = tp.sec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33201 | t.tm_wday = tp.dayofweek; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33203 | len = strftime(buf, sizeof(buf), frm, &t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33204 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33205 | d_setlocale(&prev_locale); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33207 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33208 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33209 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33210 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33211 | #define DEF_TOLOCALESTR(funcname, frm) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33212 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33213 | V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33214 | val_t this_obj = v7_get_this(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33215 | return d_tolocalestr(v7, this_obj, frm, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33216 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33218 | DEF_TOLOCALESTR(LocaleString, "%c") |
Marko Mikulicic |
0:c0ecb8bf28eb | 33219 | DEF_TOLOCALESTR(LocaleDateString, "%x") |
Marko Mikulicic |
0:c0ecb8bf28eb | 33220 | DEF_TOLOCALESTR(LocaleTimeString, "%X") |
Marko Mikulicic |
0:c0ecb8bf28eb | 33221 | #endif /* V7_ENABLE__Date__toLocaleString */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33223 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33224 | V7_PRIVATE enum v7_err Date_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33225 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33226 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33227 | if (!v7_is_generic_object(this_obj) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 33228 | (v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 33229 | v7_get_proto(v7, this_obj) != v7->vals.date_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33230 | rcode = v7_throwf(v7, TYPE_ERROR, "Date.valueOf called on non-Date object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33231 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33232 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33233 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33234 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33235 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33236 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33237 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33238 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33239 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33240 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33241 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33243 | #if V7_ENABLE__Date__getters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33244 | static struct timeparts *d_getTimePart(struct v7 *v7, val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33245 | struct timeparts *tp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33246 | fbreaktime_t breaktimefunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33247 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33248 | time = v7_get_double(v7, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33249 | breaktimefunc(&time, tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33250 | return tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33251 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33253 | #define DEF_GET_TP_FUNC(funcName, tpmember, breaktimefunc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33254 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33255 | V7_PRIVATE enum v7_err Date_get##funcName(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33256 | enum v7_err rcode = V7_OK; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33257 | val_t v = V7_UNDEFINED; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33258 | struct timeparts tp; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33259 | val_t this_obj = v7_get_this(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33260 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33261 | rcode = obj_value_of(v7, this_obj, &v); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33262 | if (rcode != V7_OK) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33263 | goto clean; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33264 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33265 | *res = v7_mk_number( \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33266 | v7, v == V7_TAG_NAN ? NAN : d_getTimePart(v7, v, &tp, breaktimefunc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33267 | ->tpmember); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33268 | clean: \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33269 | return rcode; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33270 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33272 | #define DEF_GET_TP(funcName, tpmember) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33273 | DEF_GET_TP_FUNC(UTC##funcName, tpmember, d_gmtime) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33274 | DEF_GET_TP_FUNC(funcName, tpmember, d_localtime) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33275 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33276 | DEF_GET_TP(Date, day) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33277 | DEF_GET_TP(FullYear, year) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33278 | DEF_GET_TP(Month, month) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33279 | DEF_GET_TP(Hours, hour) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33280 | DEF_GET_TP(Minutes, min) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33281 | DEF_GET_TP(Seconds, sec) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33282 | DEF_GET_TP(Milliseconds, msec) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33283 | DEF_GET_TP(Day, dayofweek) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33285 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33286 | V7_PRIVATE enum v7_err Date_getTime(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33287 | return Date_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33288 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33290 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33291 | V7_PRIVATE enum v7_err Date_getTimezoneOffset(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33292 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33293 | *res = v7_mk_number(v7, g_gmtoffms / msPerMinute); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33294 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33296 | #endif /* V7_ENABLE__Date__getters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33298 | #if V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33299 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33300 | static enum v7_err d_setTimePart(struct v7 *v7, int start_pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33301 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33302 | fmaketime_t maketimefunc, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33303 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33304 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33305 | etime_t ret_time = |
Marko Mikulicic |
0:c0ecb8bf28eb | 33306 | d_time_number_from_arr(v7, start_pos, breaktimefunc, maketimefunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33308 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33309 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33311 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33314 | #define DEF_SET_TP(name, start_pos) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33315 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33316 | V7_PRIVATE enum v7_err Date_setUTC##name(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33317 | return d_setTimePart(v7, start_pos, d_gmtime, d_gmktime, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33318 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33319 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33320 | V7_PRIVATE enum v7_err Date_set##name(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33321 | return d_setTimePart(v7, start_pos, d_localtime, d_lmktime, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33324 | DEF_SET_TP(Milliseconds, tpmsec) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33325 | DEF_SET_TP(Seconds, tpseconds) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33326 | DEF_SET_TP(Minutes, tpminutes) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33327 | DEF_SET_TP(Hours, tphours) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33328 | DEF_SET_TP(Date, tpdate) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33329 | DEF_SET_TP(Month, tpmonth) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33330 | DEF_SET_TP(FullYear, tpyear) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33332 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33333 | V7_PRIVATE enum v7_err Date_setTime(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33334 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33335 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33337 | if (v7_argc(v7) >= 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33338 | rcode = to_number_v(v7, v7_arg(v7, 0), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33339 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33340 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33344 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33346 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33347 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33348 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33349 | #endif /* V7_ENABLE__Date__setters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33351 | #if V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 33352 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33353 | V7_PRIVATE enum v7_err Date_toJSON(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33354 | return Date_toISOString(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33355 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33356 | #endif /* V7_ENABLE__Date__toJSON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33358 | #if V7_ENABLE__Date__now |
Marko Mikulicic |
0:c0ecb8bf28eb | 33359 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33360 | V7_PRIVATE enum v7_err Date_now(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33361 | etime_t ret_time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33362 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33364 | d_gettime(&ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33366 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33367 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33368 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33369 | #endif /* V7_ENABLE__Date__now */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33371 | #if V7_ENABLE__Date__parse |
Marko Mikulicic |
0:c0ecb8bf28eb | 33372 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33373 | V7_PRIVATE enum v7_err Date_parse(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33374 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33375 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33376 | etime_t ret_time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33378 | if (!d_iscalledasfunction(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33379 | rcode = v7_throwf(v7, TYPE_ERROR, "Date.parse() called on object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33380 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33381 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33383 | if (v7_argc(v7) >= 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33384 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33385 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33386 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33387 | const char *time_str = v7_get_string(v7, &arg0, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33389 | d_timeFromString(&ret_time, time_str, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33390 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33391 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33393 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33394 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33395 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33396 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33397 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33398 | #endif /* V7_ENABLE__Date__parse */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33400 | #if V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 33401 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33402 | V7_PRIVATE enum v7_err Date_UTC(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33403 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33404 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33405 | etime_t ret_time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33406 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33407 | if (!d_iscalledasfunction(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33408 | rcode = v7_throwf(v7, TYPE_ERROR, "Date.now() called on object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33409 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33410 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33412 | ret_time = d_time_number_from_arr(v7, tpyear, 0, d_gmktime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33413 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33415 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33416 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33417 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33418 | #endif /* V7_ENABLE__Date__UTC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33419 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33420 | /****** Initialization *******/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33422 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33423 | * We should clear V7_PROPERTY_ENUMERABLE for all Date props |
Marko Mikulicic |
0:c0ecb8bf28eb | 33424 | * TODO(mkm): check other objects |
Marko Mikulicic |
0:c0ecb8bf28eb | 33425 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33426 | static int d_set_cfunc_prop(struct v7 *v7, val_t o, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33427 | v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33428 | return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33429 | v7_mk_cfunction(f)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33430 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33432 | #define DECLARE_GET(func) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33433 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "getUTC" #func, \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33434 | Date_getUTC##func); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33435 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "get" #func, Date_get##func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33436 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33437 | #define DECLARE_SET(func) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33438 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "setUTC" #func, \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33439 | Date_setUTC##func); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33440 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "set" #func, Date_set##func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33442 | V7_PRIVATE void init_date(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33443 | val_t date = |
Marko Mikulicic |
0:c0ecb8bf28eb | 33444 | mk_cfunction_obj_with_proto(v7, Date_ctor, 7, v7->vals.date_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33445 | v7_def(v7, v7->vals.global_object, "Date", 4, V7_DESC_ENUMERABLE(0), date); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33446 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "valueOf", Date_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33448 | #if V7_ENABLE__Date__getters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33449 | DECLARE_GET(Date); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33450 | DECLARE_GET(FullYear); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33451 | DECLARE_GET(Month); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33452 | DECLARE_GET(Hours); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33453 | DECLARE_GET(Minutes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33454 | DECLARE_GET(Seconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33455 | DECLARE_GET(Milliseconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33456 | DECLARE_GET(Day); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33457 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTime", Date_getTime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33458 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33460 | #if V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33461 | DECLARE_SET(Date); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33462 | DECLARE_SET(FullYear); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33463 | DECLARE_SET(Month); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33464 | DECLARE_SET(Hours); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33465 | DECLARE_SET(Minutes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33466 | DECLARE_SET(Seconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33467 | DECLARE_SET(Milliseconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33468 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "setTime", Date_setTime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33469 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTimezoneOffset", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33470 | Date_getTimezoneOffset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33471 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33473 | #if V7_ENABLE__Date__now |
Marko Mikulicic |
0:c0ecb8bf28eb | 33474 | d_set_cfunc_prop(v7, date, "now", Date_now); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33475 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33476 | #if V7_ENABLE__Date__parse |
Marko Mikulicic |
0:c0ecb8bf28eb | 33477 | d_set_cfunc_prop(v7, date, "parse", Date_parse); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33478 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33479 | #if V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 33480 | d_set_cfunc_prop(v7, date, "UTC", Date_UTC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33481 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33483 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33484 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toString", Date_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33485 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toISOString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33486 | Date_toISOString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33487 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toUTCString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33488 | Date_toUTCString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33489 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toDateString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33490 | Date_toDateString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33491 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toTimeString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33492 | Date_toTimeString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33493 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33494 | #if V7_ENABLE__Date__toLocaleString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33495 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33496 | Date_toLocaleString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33497 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleDateString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33498 | Date_toLocaleDateString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33499 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleTimeString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33500 | Date_toLocaleTimeString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33501 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33502 | #if V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 33503 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toJSON", Date_toJSON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33504 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33506 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33507 | * GTM offset without DST |
Marko Mikulicic |
0:c0ecb8bf28eb | 33508 | * TODO(alashkin): check this |
Marko Mikulicic |
0:c0ecb8bf28eb | 33509 | * Could be changed to tm::tm_gmtoff, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33510 | * but tm_gmtoff includes DST, so |
Marko Mikulicic |
0:c0ecb8bf28eb | 33511 | * side effects are possible |
Marko Mikulicic |
0:c0ecb8bf28eb | 33512 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33513 | tzset(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33514 | g_gmtoffms = timezone * msPerSecond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33515 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33516 | * tzname could be changed by localtime_r call, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33517 | * so we have to store pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 33518 | * TODO(alashkin): need restart on tz change??? |
Marko Mikulicic |
0:c0ecb8bf28eb | 33519 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33520 | g_tzname = tzname[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33521 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33523 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33525 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33527 | #endif /* V7_ENABLE__Date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33528 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 33529 | #line 1 "v7/src/std_function.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 33530 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33531 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33532 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 33533 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 33534 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33536 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33537 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33538 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33539 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33540 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33541 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33542 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33543 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33544 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33545 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33546 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33547 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33548 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33549 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33550 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33551 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33552 | V7_PRIVATE enum v7_err Function_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33553 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33554 | long i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33555 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33556 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33557 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33558 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33559 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33561 | if (num_args <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33562 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33563 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33565 | mbuf_append(&m, "(function(", 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33567 | for (i = 0; i < num_args - 1; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33568 | rcode = obj_value_of(v7, v7_arg(v7, i), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33569 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33570 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33571 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33572 | if (v7_is_string(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33573 | if (i > 0) mbuf_append(&m, ",", 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33574 | s = v7_get_string(v7, res, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33575 | mbuf_append(&m, s, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33576 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33577 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33578 | mbuf_append(&m, "){", 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33579 | rcode = obj_value_of(v7, v7_arg(v7, num_args - 1), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33580 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33581 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33582 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33583 | if (v7_is_string(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33584 | s = v7_get_string(v7, res, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33585 | mbuf_append(&m, s, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33586 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33587 | mbuf_append(&m, "})\0", 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33589 | rcode = v7_exec(v7, m.buf, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33590 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33591 | rcode = v7_throwf(v7, SYNTAX_ERROR, "Invalid function body"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33592 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33593 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33594 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33595 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33596 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33597 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33598 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33599 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33600 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33601 | V7_PRIVATE enum v7_err Function_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33602 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33603 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33604 | struct v7_js_function *func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33605 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33606 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33607 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33608 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33609 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33610 | if (!is_js_function(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33611 | *res = v7_mk_number(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33612 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33613 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33615 | func = get_js_function_struct(this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33616 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33617 | *res = v7_mk_number(v7, func->bcode->args_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33618 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33619 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33620 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33621 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33623 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33624 | V7_PRIVATE enum v7_err Function_name(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33625 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33626 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33627 | struct v7_js_function *func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33628 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33629 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33630 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33631 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33633 | if (!is_js_function(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33634 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33637 | func = get_js_function_struct(this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33638 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33639 | assert(func->bcode != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33640 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33641 | assert(func->bcode->names_cnt >= 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33642 | bcode_next_name_v(v7, func->bcode, func->bcode->ops.p, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33644 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33645 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33646 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33648 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33649 | V7_PRIVATE enum v7_err Function_apply(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33650 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33651 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33652 | val_t this_arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33653 | val_t func_args = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33655 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33656 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33657 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33658 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33659 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33660 | if (is_js_function(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33661 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33662 | * `Function_apply` is a cfunction, so, GC is inhibited before calling it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 33663 | * But the given function to call is a JS function, so we should enable GC; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33664 | * otherwise, it will be inhibited during the whole execution of the given |
Marko Mikulicic |
0:c0ecb8bf28eb | 33665 | * JS function |
Marko Mikulicic |
0:c0ecb8bf28eb | 33666 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33667 | v7_set_gc_enabled(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33668 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33669 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33670 | rcode = b_apply(v7, this_obj, this_arg, func_args, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33671 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33672 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33673 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33675 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33676 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33679 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33680 | V7_PRIVATE enum v7_err Function_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33681 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33682 | char *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33683 | char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33684 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33685 | char buf[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33686 | char *b = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33687 | struct v7_js_function *func = get_js_function_struct(v7_get_this(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33688 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33690 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "[function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33692 | assert(func->bcode != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33693 | ops = func->bcode->ops.p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33694 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33695 | /* first entry in name list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33696 | ops = bcode_next_name(ops, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33697 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33698 | if (name_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33699 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), " %.*s", (int) name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33700 | name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33701 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33702 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "("); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33703 | for (i = 0; i < func->bcode->args_cnt; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33704 | ops = bcode_next_name(ops, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33706 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s", (int) name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33707 | name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33708 | if (i < func->bcode->args_cnt - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33709 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33710 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33711 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33712 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33713 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33714 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33715 | uint8_t loc_cnt = |
Marko Mikulicic |
0:c0ecb8bf28eb | 33716 | func->bcode->names_cnt - func->bcode->args_cnt - 1 /*func name*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33717 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33718 | if (loc_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33719 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "{var "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33720 | for (i = 0; i < loc_cnt; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33721 | ops = bcode_next_name(ops, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33723 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33724 | (int) name_len, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33725 | if (i < (loc_cnt - 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33726 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33727 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33728 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33730 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33731 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33732 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33733 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33734 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "]"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33736 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33737 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33738 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33739 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33741 | V7_PRIVATE void init_function(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33742 | val_t ctor = mk_cfunction_obj(v7, Function_ctor, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33743 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33744 | v7_set(v7, ctor, "prototype", 9, v7->vals.function_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33745 | v7_set(v7, v7->vals.global_object, "Function", 8, ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33746 | set_method(v7, v7->vals.function_prototype, "apply", Function_apply, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33747 | set_method(v7, v7->vals.function_prototype, "toString", Function_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33748 | v7_def(v7, v7->vals.function_prototype, "length", 6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33749 | (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33750 | v7_mk_cfunction(Function_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33751 | v7_def(v7, v7->vals.function_prototype, "name", 4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33752 | (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33753 | v7_mk_cfunction(Function_name)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33754 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33756 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33757 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33758 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33759 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 33760 | #line 1 "v7/src/std_regex.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 33761 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33762 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33763 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 33764 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 33765 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33767 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33768 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33769 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33770 | /* Amalgamated: #include "v7/src/std_regex.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33771 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33772 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33773 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33774 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33775 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33776 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33777 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33778 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33779 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33780 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33781 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33783 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 33784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33785 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33786 | V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33787 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33788 | long argnum = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33789 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33790 | if (argnum > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33791 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33792 | val_t ro, fl; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33793 | size_t re_len, flags_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33794 | const char *re, *flags = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33796 | if (v7_is_regexp(v7, arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33797 | if (argnum > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33798 | /* ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33799 | rcode = v7_throwf(v7, TYPE_ERROR, "invalid flags"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33800 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33801 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33802 | *res = arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33803 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33804 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33805 | rcode = to_string(v7, arg, &ro, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33806 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33807 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33808 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33810 | if (argnum > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33811 | rcode = to_string(v7, v7_arg(v7, 1), &fl, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33812 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33813 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33816 | flags = v7_get_string(v7, &fl, &flags_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33817 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33818 | re = v7_get_string(v7, &ro, &re_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33819 | rcode = v7_mk_regexp(v7, re, re_len, flags, flags_len, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33820 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33821 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33822 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33824 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33825 | rcode = v7_mk_regexp(v7, "(?:)", 4, NULL, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33826 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33827 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33828 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33829 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33831 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33832 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33833 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33835 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33836 | V7_PRIVATE enum v7_err Regex_global(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33837 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33838 | int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33839 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33840 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33841 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33842 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33843 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33846 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33847 | flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33848 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33850 | *res = v7_mk_boolean(v7, flags & SLRE_FLAG_G); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33852 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33853 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33854 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33855 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33856 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33857 | V7_PRIVATE enum v7_err Regex_ignoreCase(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33858 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33859 | int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33860 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33861 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33862 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33863 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33864 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33867 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33868 | flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33869 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33871 | *res = v7_mk_boolean(v7, flags & SLRE_FLAG_I); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33873 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33874 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33875 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33876 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33877 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33878 | V7_PRIVATE enum v7_err Regex_multiline(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33879 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33880 | int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33881 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33882 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33883 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33884 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33885 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33888 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33889 | flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33890 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33892 | *res = v7_mk_boolean(v7, flags & SLRE_FLAG_M); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33894 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33895 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33898 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33899 | V7_PRIVATE enum v7_err Regex_source(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33900 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33901 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33902 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33903 | const char *buf = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33904 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33906 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33907 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33908 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33909 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33911 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33912 | buf = v7_get_string(v7, &v7_get_regexp_struct(v7, r)->regexp_string, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33913 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33915 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33917 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33918 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33920 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33921 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33922 | V7_PRIVATE enum v7_err Regex_get_lastIndex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33923 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33924 | long lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33925 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33927 | if (v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33928 | lastIndex = v7_get_regexp_struct(v7, this_obj)->lastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33929 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33931 | *res = v7_mk_number(v7, lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33933 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33934 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33936 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33937 | V7_PRIVATE enum v7_err Regex_set_lastIndex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33938 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33939 | long lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33940 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33942 | if (v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33943 | rcode = to_long(v7, v7_arg(v7, 0), 0, &lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33944 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33945 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33946 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33947 | v7_get_regexp_struct(v7, this_obj)->lastIndex = lastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33948 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33950 | *res = v7_mk_number(v7, lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33952 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33953 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33954 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33956 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33957 | V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, val_t rx, val_t vstr, int lind, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33958 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33959 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33960 | if (v7_is_regexp(v7, rx)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33961 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33962 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33963 | struct slre_loot sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33964 | struct slre_cap *ptok = sub.caps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33965 | const char *str = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33966 | const char *end = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33967 | const char *begin = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33968 | struct v7_regexp *rp = v7_get_regexp_struct(v7, rx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33969 | int flag_g = slre_get_flags(rp->compiled_regexp) & SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33971 | rcode = to_string(v7, vstr, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33972 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33973 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33974 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33975 | str = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33976 | end = str + len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33977 | begin = str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33979 | if (rp->lastIndex < 0) rp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33980 | if (flag_g || lind) begin = utfnshift(str, rp->lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33982 | if (!slre_exec(rp->compiled_regexp, 0, begin, end, &sub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33983 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33984 | val_t arr = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33985 | char *old_mbuf_base = v7->owned_strings.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33986 | ptrdiff_t rel = 0; /* creating strings might relocate the mbuf */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33988 | for (i = 0; i < sub.num_captures; i++, ptok++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33989 | rel = v7->owned_strings.buf - old_mbuf_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33990 | v7_array_push(v7, arr, v7_mk_string(v7, ptok->start + rel, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33991 | ptok->end - ptok->start, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33993 | if (flag_g) rp->lastIndex = utfnlen(str, sub.caps->end + rel - str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33994 | v7_def(v7, arr, "index", 5, V7_DESC_WRITABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33995 | v7_mk_number(v7, utfnlen(str + rel, sub.caps->start - str))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33996 | *res = arr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33997 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33998 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33999 | rp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34001 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34003 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34005 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34006 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34009 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34010 | V7_PRIVATE enum v7_err Regex_exec(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34011 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34012 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34014 | if (v7_argc(v7) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34015 | rcode = rx_exec(v7, this_obj, v7_arg(v7, 0), 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34016 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34017 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34019 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34020 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34021 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34022 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34023 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34024 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34025 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34027 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34028 | V7_PRIVATE enum v7_err Regex_test(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34029 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34030 | val_t tmp = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34031 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34032 | rcode = Regex_exec(v7, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34033 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34034 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34035 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34037 | *res = v7_mk_boolean(v7, !v7_is_null(tmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34039 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34040 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34041 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34042 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34043 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34044 | V7_PRIVATE enum v7_err Regex_flags(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34045 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34046 | char buf[3] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34047 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34048 | struct v7_regexp *rp = v7_get_regexp_struct(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34049 | size_t n = get_regexp_flags_str(v7, rp, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34050 | *res = v7_mk_string(v7, buf, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34052 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34053 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34054 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34055 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34056 | V7_PRIVATE enum v7_err Regex_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34057 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34058 | size_t n1, n2 = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34059 | char s2[3] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34060 | char buf[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34061 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34062 | struct v7_regexp *rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34063 | const char *s1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34065 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34066 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34067 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34068 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34070 | if (!v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34071 | rcode = v7_throwf(v7, TYPE_ERROR, "Not a regexp"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34072 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34073 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34074 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34075 | rp = v7_get_regexp_struct(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34076 | s1 = v7_get_string(v7, &rp->regexp_string, &n1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34077 | n2 = get_regexp_flags_str(v7, rp, s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34079 | c_snprintf(buf, sizeof(buf), "/%.*s/%.*s", (int) n1, s1, (int) n2, s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34080 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34081 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34083 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34084 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34085 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34086 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34087 | V7_PRIVATE void init_regex(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34088 | val_t ctor = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34089 | mk_cfunction_obj_with_proto(v7, Regex_ctor, 1, v7->vals.regexp_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34090 | val_t lastIndex = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34091 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34092 | v7_def(v7, v7->vals.global_object, "RegExp", 6, V7_DESC_ENUMERABLE(0), ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34094 | set_cfunc_prop(v7, v7->vals.regexp_prototype, "exec", Regex_exec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34095 | set_cfunc_prop(v7, v7->vals.regexp_prototype, "test", Regex_test); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34096 | set_method(v7, v7->vals.regexp_prototype, "toString", Regex_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34098 | v7_def(v7, v7->vals.regexp_prototype, "global", 6, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34099 | v7_mk_cfunction(Regex_global)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34100 | v7_def(v7, v7->vals.regexp_prototype, "ignoreCase", 10, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34101 | v7_mk_cfunction(Regex_ignoreCase)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34102 | v7_def(v7, v7->vals.regexp_prototype, "multiline", 9, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34103 | v7_mk_cfunction(Regex_multiline)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34104 | v7_def(v7, v7->vals.regexp_prototype, "source", 6, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34105 | v7_mk_cfunction(Regex_source)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34106 | v7_def(v7, v7->vals.regexp_prototype, "flags", 5, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34107 | v7_mk_cfunction(Regex_flags)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34109 | v7_array_set(v7, lastIndex, 0, v7_mk_cfunction(Regex_get_lastIndex)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34110 | v7_array_set(v7, lastIndex, 1, v7_mk_cfunction(Regex_set_lastIndex)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34111 | v7_def(v7, v7->vals.regexp_prototype, "lastIndex", 9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 34112 | (V7_DESC_GETTER(1) | V7_DESC_SETTER(1)), lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34113 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34115 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34116 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 34117 | #line 1 "v7/src/std_proxy.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 34118 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34119 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 34120 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 34121 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 34122 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34123 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34124 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34125 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34126 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34127 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34128 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34129 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34130 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34131 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34132 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34133 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34135 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34136 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34137 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34139 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 34140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34141 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34142 | V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34143 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34144 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34145 | val_t target_v = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34146 | val_t handler_v = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34147 | struct v7_object *t = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34148 | v7_prop_attr_desc_t attrs_desc = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34149 | (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34151 | if (this_obj == v7_get_global(v7) || !v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34152 | rcode = v7_throwf(v7, TYPE_ERROR, "Wrong 'this' object for Proxy ctor"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34153 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34156 | if (!v7_is_object(target_v) || !v7_is_object(handler_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34157 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34158 | v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 34159 | "Cannot create proxy with a non-object as target or handler"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34160 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34161 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34162 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34163 | t = get_object_struct(this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34164 | t->attributes |= V7_OBJ_PROXY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34166 | v7_def(v7, this_obj, _V7_PROXY_TARGET_NAME, ~0, attrs_desc, target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34167 | v7_def(v7, this_obj, _V7_PROXY_HANDLER_NAME, ~0, attrs_desc, handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34169 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34170 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34171 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34172 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34175 | V7_PRIVATE void init_proxy(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34176 | /*v7_prop_attr_desc_t attrs_desc =*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34177 | /*(V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34178 | val_t proxy = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34179 | mk_cfunction_obj_with_proto(v7, Proxy_ctor, 1, v7->vals.proxy_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34180 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34181 | v7_def(v7, v7->vals.global_object, "Proxy", ~0, V7_DESC_ENUMERABLE(0), proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34182 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34183 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34184 | V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34185 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34186 | if (name_len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34187 | name_len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34188 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34189 | if (name_len == 5 && (memcmp(name, _V7_PROXY_TARGET_NAME, name_len) == 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 34190 | memcmp(name, _V7_PROXY_HANDLER_NAME, name_len) == 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34191 | ret = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34193 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34194 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34195 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34196 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34198 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34199 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34200 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34201 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 34202 | #line 1 "v7/src/main.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 34203 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34204 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 34205 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 34206 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 34207 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34209 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34210 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34211 | /* Amalgamated: #include "v7/src/freeze.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34212 | /* Amalgamated: #include "v7/src/main.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34213 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34214 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34215 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34216 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34217 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34218 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34220 | #if defined(_MSC_VER) && _MSC_VER >= 1800 |
Marko Mikulicic |
0:c0ecb8bf28eb | 34221 | #define fileno _fileno |
Marko Mikulicic |
0:c0ecb8bf28eb | 34222 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34223 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34224 | #ifdef V7_EXE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34225 | #define V7_MAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 34226 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34228 | #ifdef V7_MAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 34229 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34230 | #include <sys/stat.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 34231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34232 | static void show_usage(char *argv[]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34233 | fprintf(stderr, "V7 version %s (c) Cesanta Software, built on %s\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34234 | V7_VERSION, __DATE__); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34235 | fprintf(stderr, "Usage: %s [OPTIONS] js_file ...\n", argv[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34236 | fprintf(stderr, "%s\n", "OPTIONS:"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34237 | fprintf(stderr, "%s\n", " -e <expr> execute expression"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34238 | fprintf(stderr, "%s\n", " -t dump generated text AST"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34239 | fprintf(stderr, "%s\n", " -b dump generated binary AST"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34240 | fprintf(stderr, "%s\n", " -c dump compiled binary bcode"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34241 | fprintf(stderr, "%s\n", " -mm dump memory stats"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34242 | fprintf(stderr, "%s\n", " -vo <n> object arena size"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34243 | fprintf(stderr, "%s\n", " -vf <n> function arena size"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34244 | fprintf(stderr, "%s\n", " -vp <n> property arena size"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34245 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34246 | fprintf(stderr, "%s\n", " -freeze filename dump JS heap into a file"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34247 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34248 | exit(EXIT_FAILURE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34251 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 34252 | static void dump_mm_arena_stats(const char *msg, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34253 | printf("%s: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34254 | ", alive %lu\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34255 | msg, a->allocations, a->garbage, gc_arena_size(a), a->alive); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34256 | printf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 34257 | "%s: (bytes: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34258 | ", alive %lu)\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34259 | msg, a->allocations * a->cell_size, a->garbage * a->cell_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 34260 | gc_arena_size(a) * a->cell_size, a->alive * a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34261 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34263 | static void dump_mm_stats(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34264 | dump_mm_arena_stats("object: ", &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34265 | dump_mm_arena_stats("function: ", &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34266 | dump_mm_arena_stats("property: ", &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34267 | printf("string arena len: %" SIZE_T_FMT "\n", v7->owned_strings.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34268 | printf("Total heap size: %" SIZE_T_FMT "\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34269 | v7->owned_strings.len + |
Marko Mikulicic |
0:c0ecb8bf28eb | 34270 | gc_arena_size(&v7->generic_object_arena) * |
Marko Mikulicic |
0:c0ecb8bf28eb | 34271 | v7->generic_object_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 34272 | gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 34273 | gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34274 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34275 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34277 | int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34278 | void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34279 | int exit_rcode = EXIT_SUCCESS; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34280 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34281 | struct v7_create_opts opts; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34282 | int as_json = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34283 | int i, j, show_ast = 0, binary_ast = 0, dump_bcode = 0, dump_stats = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34284 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34285 | int nexprs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34286 | const char *exprs[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34288 | memset(&opts, 0, sizeof(opts)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34290 | (void) show_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34291 | (void) binary_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34292 | (void) dump_bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34293 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34294 | /* Execute inline code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34295 | for (i = 1; i < argc && argv[i][0] == '-'; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34296 | if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34297 | exprs[nexprs++] = argv[i + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34298 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34299 | } else if (strcmp(argv[i], "-t") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34300 | show_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34301 | } else if (strcmp(argv[i], "-b") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34302 | show_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34303 | binary_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34304 | } else if (strcmp(argv[i], "-c") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34305 | binary_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34306 | dump_bcode = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34307 | } else if (strcmp(argv[i], "-h") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34308 | show_usage(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34309 | } else if (strcmp(argv[i], "-j") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34310 | as_json = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34311 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 34312 | } else if (strcmp(argv[i], "-mm") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34313 | dump_stats = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34314 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34315 | } else if (strcmp(argv[i], "-vo") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34316 | opts.object_arena_size = atoi(argv[i + 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34317 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34318 | } else if (strcmp(argv[i], "-vf") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34319 | opts.function_arena_size = atoi(argv[i + 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34320 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34321 | } else if (strcmp(argv[i], "-vp") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34322 | opts.property_arena_size = atoi(argv[i + 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34323 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34324 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34325 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34326 | else if (strcmp(argv[i], "-freeze") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34327 | opts.freeze_file = argv[i + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34328 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34329 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34330 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34331 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34333 | #ifndef V7_ALLOW_ARGLESS_MAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 34334 | if (argc == 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34335 | show_usage(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34336 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34337 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34339 | v7 = v7_create_opt(opts); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34340 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34342 | if (pre_freeze_init != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34343 | pre_freeze_init(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34346 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34347 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 34348 | * Skip pre_init if freezing, but still execute cmdline expressions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 34349 | * This makes it easier to add custom code when freezing from cmdline. |
Marko Mikulicic |
0:c0ecb8bf28eb | 34350 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34351 | if (opts.freeze_file == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34352 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34354 | if (pre_init != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34355 | pre_init(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34356 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34358 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34360 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34362 | #if V7_ENABLE__Memory__stats > 0 && !defined(V7_DISABLE_GC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34363 | if (dump_stats) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34364 | printf("Memory stats during init:\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34365 | dump_mm_stats(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34366 | v7_gc(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34367 | printf("Memory stats before run:\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34368 | dump_mm_stats(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34370 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 34371 | (void) dump_stats; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34372 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34374 | /* Execute inline expressions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34375 | for (j = 0; j < nexprs; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34376 | enum v7_err (*exec)(struct v7 *, const char *, v7_val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34377 | exec = v7_exec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34379 | if (show_ast || dump_bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34380 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34381 | if (v7_compile(exprs[j], binary_ast, dump_bcode, stdout) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34382 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34383 | fprintf(stderr, "%s\n", "parse error"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34384 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34385 | #else /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34386 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34387 | fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34388 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34389 | } else if (exec(v7, exprs[j], &res) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34390 | v7_print_error(stderr, v7, exprs[j], res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34391 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34392 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34394 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34396 | /* Execute files */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34397 | for (; i < argc; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34398 | if (show_ast || dump_bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34399 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34400 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34401 | char *source_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34402 | if ((source_code = cs_read_file(argv[i], &size)) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34403 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34404 | fprintf(stderr, "Cannot read [%s]\n", argv[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34405 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34406 | if (_v7_compile(source_code, size, binary_ast, dump_bcode, stdout) != |
Marko Mikulicic |
0:c0ecb8bf28eb | 34407 | V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34408 | fprintf(stderr, "error: %s\n", v7->error_msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34409 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34410 | exit(exit_rcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34411 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34412 | free(source_code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34413 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34414 | #else /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34415 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34416 | fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34417 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34418 | } else if (v7_exec_file(v7, argv[i], &res) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34419 | v7_print_error(stderr, v7, argv[i], res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34420 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34421 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34422 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34424 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34425 | if (opts.freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34426 | freeze(v7, opts.freeze_file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34427 | exit(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34428 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34429 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34431 | if (!(show_ast || dump_bcode)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34432 | char buf[2000]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34433 | char *s = v7_stringify(v7, res, buf, sizeof(buf), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34434 | as_json ? V7_STRINGIFY_JSON : V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34435 | printf("%s\n", s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34436 | if (s != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34437 | free(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34438 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34439 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34441 | if (post_init != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34442 | post_init(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34445 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 34446 | if (dump_stats) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34447 | printf("Memory stats after run:\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34448 | dump_mm_stats(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34449 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34450 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 34451 | (void) dump_stats; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34452 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34453 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34454 | v7_destroy(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34455 | return exit_rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34456 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34457 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34459 | #ifdef V7_EXE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34460 | int main(int argc, char *argv[]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34461 | return v7_main(argc, argv, NULL, NULL, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34462 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34463 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34464 | #endif /* V7_EXPORT_INTERNAL_HEADERS */ |