Embedded JavaScript virtual machine
Dependents: DISCO-F469NI_javascript_blinker
v7.c@3:2bce515c5f0b, 2016-10-11 (annotated)
- Committer:
- Marko Mikulicic
- Date:
- Tue Oct 11 14:30:58 2016 +0200
- Revision:
- 3:2bce515c5f0b
- Parent:
- 2:7762b98d31c7
Fix armcc build
armcc toolchain seems to lack sys/time.h, disabling the JS Date feature
for now.
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 |
3:2bce515c5f0b | 1856 | #line 1 "v7/src/platform.h" |
Marko Mikulicic |
3:2bce515c5f0b | 1857 | #endif |
Marko Mikulicic |
3:2bce515c5f0b | 1858 | /* |
Marko Mikulicic |
3:2bce515c5f0b | 1859 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
3:2bce515c5f0b | 1860 | * All rights reserved |
Marko Mikulicic |
3:2bce515c5f0b | 1861 | */ |
Marko Mikulicic |
3:2bce515c5f0b | 1862 | |
Marko Mikulicic |
3:2bce515c5f0b | 1863 | #ifndef CS_V7_SRC_PLATFORM_H_ |
Marko Mikulicic |
3:2bce515c5f0b | 1864 | #define CS_V7_SRC_PLATFORM_H_ |
Marko Mikulicic |
3:2bce515c5f0b | 1865 | |
Marko Mikulicic |
3:2bce515c5f0b | 1866 | #ifdef __arm |
Marko Mikulicic |
3:2bce515c5f0b | 1867 | #undef V7_ENABLE__Date |
Marko Mikulicic |
3:2bce515c5f0b | 1868 | #define V7_ENABLE__Date 0 |
Marko Mikulicic |
3:2bce515c5f0b | 1869 | #endif |
Marko Mikulicic |
3:2bce515c5f0b | 1870 | |
Marko Mikulicic |
3:2bce515c5f0b | 1871 | #endif /* CS_V7_SRC_PLATFORM_H_ */ |
Marko Mikulicic |
3:2bce515c5f0b | 1872 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 1873 | #line 1 "v7/src/internal.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1874 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1875 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1876 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 1877 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 1878 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1880 | #ifndef CS_V7_SRC_INTERNAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1881 | #define CS_V7_SRC_INTERNAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1882 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1883 | /* Amalgamated: #include "v7/src/license.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1885 | /* Check whether we're compiling in an environment with no filesystem */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1886 | #if defined(ARDUINO) && (ARDUINO == 106) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1887 | #define V7_NO_FS |
Marko Mikulicic |
0:c0ecb8bf28eb | 1888 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1890 | #ifndef FAST |
Marko Mikulicic |
0:c0ecb8bf28eb | 1891 | #define FAST |
Marko Mikulicic |
0:c0ecb8bf28eb | 1892 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1894 | #ifndef STATIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 1895 | #define STATIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 1896 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1898 | #ifndef ENDL |
Marko Mikulicic |
0:c0ecb8bf28eb | 1899 | #define ENDL "\n" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1900 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1901 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1902 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 1903 | * In some compilers (watcom) NAN == NAN (and other comparisons) don't follow |
Marko Mikulicic |
0:c0ecb8bf28eb | 1904 | * the rules of IEEE 754. Since we don't know a priori which compilers |
Marko Mikulicic |
0:c0ecb8bf28eb | 1905 | * will generate correct code, we disable the fallback on selected platforms. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1906 | * TODO(mkm): selectively disable on clang/gcc once we test this out. |
Marko Mikulicic |
0:c0ecb8bf28eb | 1907 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1908 | #define V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 1909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1910 | #undef _POSIX_C_SOURCE |
Marko Mikulicic |
0:c0ecb8bf28eb | 1911 | #define _POSIX_C_SOURCE 200809L |
Marko Mikulicic |
0:c0ecb8bf28eb | 1912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1913 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1914 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 1915 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1916 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1917 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1918 | #include <float.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1919 | #include <limits.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1920 | #include <math.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1921 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1922 | #include <stddef.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1923 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1924 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1925 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1926 | #include <setjmp.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1928 | /* Public API. Implemented in api.c */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1929 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1931 | #ifdef V7_WINDOWS |
Marko Mikulicic |
0:c0ecb8bf28eb | 1932 | #define vsnprintf _vsnprintf |
Marko Mikulicic |
0:c0ecb8bf28eb | 1933 | #define snprintf _snprintf |
Marko Mikulicic |
0:c0ecb8bf28eb | 1934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1935 | /* VS2015 Update 1 has ISO C99 `isnan` and `isinf` defined in math.h */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1936 | #if _MSC_FULL_VER < 190023506 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1937 | #define isnan(x) _isnan(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1938 | #define isinf(x) (!_finite(x)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1939 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1941 | #define __unused __pragma(warning(suppress : 4100)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 1942 | typedef __int64 int64_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1943 | typedef int int32_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1944 | typedef unsigned int uint32_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1945 | typedef unsigned short uint16_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1946 | typedef unsigned char uint8_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1948 | /* For 64bit VisualStudio 2010 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1949 | #ifndef _UINTPTR_T_DEFINED |
Marko Mikulicic |
0:c0ecb8bf28eb | 1950 | typedef unsigned long uintptr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1951 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1953 | #ifndef __func__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1954 | #define __func__ "" |
Marko Mikulicic |
0:c0ecb8bf28eb | 1955 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1956 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1957 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 1958 | #include <stdint.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 1959 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1961 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
3:2bce515c5f0b | 1962 | /* Amalgamated: #include "v7/src/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1964 | /* MSVC6 doesn't have standard C math constants defined */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 1965 | #ifndef M_E |
Marko Mikulicic |
0:c0ecb8bf28eb | 1966 | #define M_E 2.71828182845904523536028747135266250 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1967 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1969 | #ifndef M_LOG2E |
Marko Mikulicic |
0:c0ecb8bf28eb | 1970 | #define M_LOG2E 1.44269504088896340735992468100189214 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1971 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1972 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1973 | #ifndef M_LOG10E |
Marko Mikulicic |
0:c0ecb8bf28eb | 1974 | #define M_LOG10E 0.434294481903251827651128918916605082 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1975 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1976 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1977 | #ifndef M_LN2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1978 | #define M_LN2 0.693147180559945309417232121458176568 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1979 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1981 | #ifndef M_LN10 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1982 | #define M_LN10 2.30258509299404568401799145468436421 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1983 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1984 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1985 | #ifndef M_PI |
Marko Mikulicic |
0:c0ecb8bf28eb | 1986 | #define M_PI 3.14159265358979323846264338327950288 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1987 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1989 | #ifndef M_SQRT2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1990 | #define M_SQRT2 1.41421356237309504880168872420969808 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1991 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1993 | #ifndef M_SQRT1_2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1994 | #define M_SQRT1_2 0.707106781186547524400844362104849039 |
Marko Mikulicic |
0:c0ecb8bf28eb | 1995 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 1996 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 1997 | #ifndef NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 1998 | extern double _v7_nan; |
Marko Mikulicic |
0:c0ecb8bf28eb | 1999 | #define HAS_V7_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 2000 | #define NAN (_v7_nan) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2001 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2003 | #ifndef INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 2004 | extern double _v7_infinity; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2005 | #define HAS_V7_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 2006 | #define INFINITY (_v7_infinity) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2007 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2009 | #ifndef EXIT_SUCCESS |
Marko Mikulicic |
0:c0ecb8bf28eb | 2010 | #define EXIT_SUCCESS 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2011 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2013 | #ifndef EXIT_FAILURE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2014 | #define EXIT_FAILURE 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2015 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2017 | #if defined(V7_ENABLE_GC_CHECK) || defined(V7_STACK_GUARD_MIN_SIZE) || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2018 | defined(V7_ENABLE_STACK_TRACKING) || defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2019 | /* Need to enable GCC/clang instrumentation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2020 | #define V7_CYG_PROFILE_ON |
Marko Mikulicic |
0:c0ecb8bf28eb | 2021 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2022 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2023 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2024 | extern struct v7 *v7_head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2026 | #if defined(V7_STACK_GUARD_MIN_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2027 | extern void *v7_sp_limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2028 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2029 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2031 | #ifndef ARRAY_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2032 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2033 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2035 | #define V7_STATIC_ASSERT(COND, MSG) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2036 | typedef char static_assertion_##MSG[2 * (!!(COND)) - 1] |
Marko Mikulicic |
0:c0ecb8bf28eb | 2037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2038 | #define BUF_LEFT(size, used) (((size_t)(used) < (size)) ? ((size) - (used)) : 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2040 | #endif /* CS_V7_SRC_INTERNAL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2041 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2042 | #line 1 "v7/src/core_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2043 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2044 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2045 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2046 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2047 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2048 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2049 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2050 | * === Core |
Marko Mikulicic |
0:c0ecb8bf28eb | 2051 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2053 | #ifndef CS_V7_SRC_CORE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2054 | #define CS_V7_SRC_CORE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2056 | #ifndef _POSIX_C_SOURCE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2057 | #define _POSIX_C_SOURCE 200809L |
Marko Mikulicic |
0:c0ecb8bf28eb | 2058 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2060 | /* Amalgamated: #include "v7/src/license.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2061 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
3:2bce515c5f0b | 2062 | /* Amalgamated: #include "v7/src/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2064 | #include <stddef.h> /* For size_t */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2065 | #include <stdio.h> /* For FILE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2066 | |
Marko Mikulicic |
2:7762b98d31c7 | 2067 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 2068 | extern "C" { |
Marko Mikulicic |
2:7762b98d31c7 | 2069 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 2070 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2071 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2072 | * TODO(dfrank) : improve amalgamation, so that we'll be able to include |
Marko Mikulicic |
0:c0ecb8bf28eb | 2073 | * files here, and include common/platform.h |
Marko Mikulicic |
0:c0ecb8bf28eb | 2074 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2075 | * For now, copy-pasting `WARN_UNUSED_RESULT` here |
Marko Mikulicic |
0:c0ecb8bf28eb | 2076 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2077 | #ifdef __GNUC__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2078 | #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2079 | #define NOINSTR __attribute__((no_instrument_function)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2080 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 2081 | #define WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2082 | #define NOINSTR |
Marko Mikulicic |
0:c0ecb8bf28eb | 2083 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2085 | #define V7_VERSION "1.0" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2086 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2087 | #if (defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)) || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2088 | (defined(_MSC_VER) && _MSC_VER <= 1200) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2089 | #define V7_WINDOWS |
Marko Mikulicic |
0:c0ecb8bf28eb | 2090 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2091 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2092 | #ifdef V7_WINDOWS |
Marko Mikulicic |
0:c0ecb8bf28eb | 2093 | typedef unsigned __int64 uint64_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2094 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 2095 | #include <inttypes.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 2096 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2097 | /* 64-bit value, used to store JS values */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2098 | typedef uint64_t v7_val_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2099 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2100 | /* JavaScript `null` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2101 | #define V7_NULL ((uint64_t) 0xfffe << 48) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2103 | /* JavaScript `undefined` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2104 | #define V7_UNDEFINED ((uint64_t) 0xfffd << 48) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2106 | /* This if-0 is a dirty workaround to force etags to pick `struct v7` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2107 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2108 | /* Opaque structure. V7 engine context. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2109 | struct v7 { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2110 | /* ... */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2111 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2112 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2113 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2114 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2115 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2116 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2117 | * Code which is returned by some of the v7 functions. If something other than |
Marko Mikulicic |
0:c0ecb8bf28eb | 2118 | * `V7_OK` is returned from some function, the caller function typically should |
Marko Mikulicic |
0:c0ecb8bf28eb | 2119 | * either immediately cleanup and return the code further, or handle the error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2120 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2121 | enum v7_err { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2122 | V7_OK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2123 | V7_SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2124 | V7_EXEC_EXCEPTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2125 | V7_AST_TOO_LARGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2126 | V7_INTERNAL_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2127 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2128 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2129 | /* JavaScript -> C call interface */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2130 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2131 | typedef enum v7_err(v7_cfunction_t)(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2132 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2133 | /* Create V7 instance */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2134 | struct v7 *v7_create(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2135 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2136 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2137 | * Customizations of initial V7 state; used by `v7_create_opt()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2138 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2139 | struct v7_create_opts { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2140 | size_t object_arena_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2141 | size_t function_arena_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2142 | size_t property_arena_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2143 | #ifdef V7_STACK_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2144 | void *c_stack_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2145 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2146 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2147 | /* if not NULL, dump JS heap after init */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2148 | char *freeze_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2149 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2150 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2151 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2152 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2153 | * Like `v7_create()`, but allows to customize initial v7 state, see `struct |
Marko Mikulicic |
0:c0ecb8bf28eb | 2154 | * v7_create_opts`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2155 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2156 | struct v7 *v7_create_opt(struct v7_create_opts opts); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2158 | /* Destroy V7 instance */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2159 | void v7_destroy(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2161 | /* Return root level (`global`) object of the given V7 instance. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2162 | v7_val_t v7_get_global(struct v7 *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2164 | /* Return current `this` object. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2165 | v7_val_t v7_get_this(struct v7 *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2167 | /* Return current `arguments` array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2168 | v7_val_t v7_get_arguments(struct v7 *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2170 | /* Return i-th argument */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2171 | v7_val_t v7_arg(struct v7 *v, unsigned long i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2173 | /* Return the length of `arguments` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2174 | unsigned long v7_argc(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2175 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2176 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2177 | * Tells the GC about a JS value variable/field owned |
Marko Mikulicic |
0:c0ecb8bf28eb | 2178 | * by C code. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2179 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2180 | * User C code should own v7_val_t variables |
Marko Mikulicic |
0:c0ecb8bf28eb | 2181 | * if the value's lifetime crosses any invocation |
Marko Mikulicic |
0:c0ecb8bf28eb | 2182 | * to the v7 runtime that creates new objects or new |
Marko Mikulicic |
0:c0ecb8bf28eb | 2183 | * properties and thus can potentially trigger GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2184 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2185 | * The registration of the variable prevents the GC from mistakenly treat |
Marko Mikulicic |
0:c0ecb8bf28eb | 2186 | * the object as garbage. The GC might be triggered potentially |
Marko Mikulicic |
0:c0ecb8bf28eb | 2187 | * allows the GC to update pointers |
Marko Mikulicic |
0:c0ecb8bf28eb | 2188 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2189 | * User code should also explicitly disown the variables with v7_disown once |
Marko Mikulicic |
0:c0ecb8bf28eb | 2190 | * it goes out of scope or the structure containing the v7_val_t field is freed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2191 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2192 | * Example: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2193 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2194 | * ``` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2195 | * struct v7_val cb; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2196 | * v7_own(v7, &cb); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2197 | * cb = v7_array_get(v7, args, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2198 | * // do something with cb |
Marko Mikulicic |
0:c0ecb8bf28eb | 2199 | * v7_disown(v7, &cb); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2200 | * ``` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2201 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2202 | void v7_own(struct v7 *v7, v7_val_t *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2204 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2205 | * Returns 1 if value is found, 0 otherwise |
Marko Mikulicic |
0:c0ecb8bf28eb | 2206 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2207 | int v7_disown(struct v7 *v7, v7_val_t *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2209 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2210 | * Enable or disable GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2211 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2212 | * Must be called before invoking v7_exec or v7_apply |
Marko Mikulicic |
0:c0ecb8bf28eb | 2213 | * from within a cfunction unless you know what you're doing. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2214 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2215 | * GC is disabled during execution of cfunctions in order to simplify |
Marko Mikulicic |
0:c0ecb8bf28eb | 2216 | * memory management of simple cfunctions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2217 | * However executing even small snippets of JS code causes a lot of memory |
Marko Mikulicic |
0:c0ecb8bf28eb | 2218 | * pressure. Enabling GC solves that but forces you to take care of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2219 | * reachability of your temporary V7 v7_val_t variables, as the GC needs |
Marko Mikulicic |
0:c0ecb8bf28eb | 2220 | * to know where they are since objects and strings can be either reclaimed |
Marko Mikulicic |
0:c0ecb8bf28eb | 2221 | * or relocated during a GC pass. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2222 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2223 | void v7_set_gc_enabled(struct v7 *v7, int enabled); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2224 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2225 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2226 | * Set an optional C stack limit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2227 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2228 | * It sets a flag that will cause the interpreter |
Marko Mikulicic |
0:c0ecb8bf28eb | 2229 | * to throw an InterruptedError. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2230 | * It's safe to call it from signal handlers and ISRs |
Marko Mikulicic |
0:c0ecb8bf28eb | 2231 | * on single threaded environments. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2232 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2233 | void v7_interrupt(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2234 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2235 | /* Returns last parser error message. TODO: rename it to `v7_get_error()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2236 | const char *v7_get_parser_error(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2238 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2239 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2240 | * Available if only `V7_ENABLE_STACK_TRACKING` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2241 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2242 | * Stack metric id. See `v7_stack_stat()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2243 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2244 | enum v7_stack_stat_what { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2245 | /* max stack size consumed by `i_exec()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2246 | V7_STACK_STAT_EXEC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2247 | /* max stack size consumed by `parse()` (which is called from `i_exec()`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2248 | V7_STACK_STAT_PARSER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2249 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2250 | V7_STACK_STATS_CNT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2251 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2253 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2254 | * Available if only `V7_ENABLE_STACK_TRACKING` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2255 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2256 | * Returns stack metric specified by the metric id `what`. See |
Marko Mikulicic |
0:c0ecb8bf28eb | 2257 | * `v7_stack_stat_clean()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2258 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2259 | int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2261 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2262 | * Available if only `V7_ENABLE_STACK_TRACKING` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2263 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2264 | * Clean all stack statistics gathered so far. See `v7_stack_stat()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2265 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2266 | void v7_stack_stat_clean(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2267 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2268 | |
Marko Mikulicic |
2:7762b98d31c7 | 2269 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 2270 | } |
Marko Mikulicic |
2:7762b98d31c7 | 2271 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 2272 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2273 | #endif /* CS_V7_SRC_CORE_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2274 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2275 | #line 1 "v7/src/std_error.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2276 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2277 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2278 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2279 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2280 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2282 | #ifndef CS_V7_SRC_STD_ERROR_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2283 | #define CS_V7_SRC_STD_ERROR_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2285 | /* Amalgamated: #include "v7/src/license.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2286 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2287 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2289 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2290 | * JavaScript error types |
Marko Mikulicic |
0:c0ecb8bf28eb | 2291 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2292 | #define TYPE_ERROR "TypeError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2293 | #define SYNTAX_ERROR "SyntaxError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2294 | #define REFERENCE_ERROR "ReferenceError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2295 | #define INTERNAL_ERROR "InternalError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2296 | #define RANGE_ERROR "RangeError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2297 | #define EVAL_ERROR "EvalError" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2298 | #define ERROR_CTOR_MAX 6 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2299 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2300 | * TODO(mkm): EvalError is not so important, we should guard it behind |
Marko Mikulicic |
0:c0ecb8bf28eb | 2301 | * something like `V7_ENABLE__EvalError`. However doing so makes it hard to |
Marko Mikulicic |
0:c0ecb8bf28eb | 2302 | * keep ERROR_CTOR_MAX up to date; perhaps let's find a better way of doing it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2303 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2304 | * EvalError is useful mostly because we now have ecma tests failing: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2305 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2306 | * 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 | 2307 | * +7600043 tests/ecmac.db|head -c 496): [{"message":"[EvalError] is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 2308 | * defined"}] |
Marko Mikulicic |
0:c0ecb8bf28eb | 2309 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2310 | * Those tests are not EvalError specific, and they do test that the exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 2311 | * handling machinery works as intended. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2312 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2314 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2315 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2316 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2318 | V7_PRIVATE void init_error(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2320 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2321 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2322 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2324 | #endif /* CS_V7_SRC_STD_ERROR_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2325 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2326 | #line 1 "v7/src/mm.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2327 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2328 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2329 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2330 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2331 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2333 | #ifndef CS_V7_SRC_MM_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2334 | #define CS_V7_SRC_MM_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2336 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2338 | typedef void (*gc_cell_destructor_t)(struct v7 *v7, void *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2340 | struct gc_block { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2341 | struct gc_block *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2342 | struct gc_cell *base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2343 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2344 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2346 | struct gc_arena { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2347 | struct gc_block *blocks; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2348 | size_t size_increment; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2349 | struct gc_cell *free; /* head of free list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2350 | size_t cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2352 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 2353 | unsigned long allocations; /* cumulative counter of allocations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2354 | unsigned long garbage; /* cumulative counter of garbage */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2355 | unsigned long alive; /* number of living cells */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2356 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2358 | gc_cell_destructor_t destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2360 | int verbose; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2361 | const char *name; /* for debugging purposes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2362 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2364 | #endif /* CS_V7_SRC_MM_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2365 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2366 | #line 1 "v7/src/parser.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2367 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2368 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2369 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2370 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2371 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2373 | #ifndef CS_V7_SRC_PARSER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2374 | #define CS_V7_SRC_PARSER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2376 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2377 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2379 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2381 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2382 | struct ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2383 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2384 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2385 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2386 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2388 | struct v7_pstate { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2389 | const char *file_name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2390 | const char *source_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2391 | const char *pc; /* Current parsing position */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2392 | const char *src_end; /* End of source code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2393 | int line_no; /* Line number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2394 | int prev_line_no; /* Line number of previous token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2395 | int inhibit_in; /* True while `in` expressions are inhibited */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2396 | int in_function; /* True if in a function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2397 | int in_loop; /* True if in a loop */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2398 | int in_switch; /* True if in a switch block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2399 | int in_strict; /* True if in strict mode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2400 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2402 | V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2403 | size_t src_len, int is_json); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2405 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2406 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2407 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2409 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2411 | #endif /* CS_V7_SRC_PARSER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2412 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2413 | #line 1 "v7/src/object_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2414 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2415 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2416 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2417 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2418 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2419 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2420 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2421 | * === Objects |
Marko Mikulicic |
0:c0ecb8bf28eb | 2422 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2424 | #ifndef CS_V7_SRC_OBJECT_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2425 | #define CS_V7_SRC_OBJECT_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2427 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2429 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2430 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2431 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2432 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2433 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2434 | * Property attributes bitmask |
Marko Mikulicic |
0:c0ecb8bf28eb | 2435 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2436 | typedef unsigned short v7_prop_attr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2437 | #define V7_PROPERTY_NON_WRITABLE (1 << 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2438 | #define V7_PROPERTY_NON_ENUMERABLE (1 << 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2439 | #define V7_PROPERTY_NON_CONFIGURABLE (1 << 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2440 | #define V7_PROPERTY_GETTER (1 << 3) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2441 | #define V7_PROPERTY_SETTER (1 << 4) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2442 | #define _V7_PROPERTY_HIDDEN (1 << 5) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2443 | /* property not managed by V7 HEAP */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2444 | #define _V7_PROPERTY_OFF_HEAP (1 << 6) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2445 | /* special property holding user data and destructor cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2446 | #define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR (1 << 7) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2447 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2448 | * not a property attribute, but a flag for `v7_def()`. It's here in order to |
Marko Mikulicic |
0:c0ecb8bf28eb | 2449 | * keep all offsets in one place |
Marko Mikulicic |
0:c0ecb8bf28eb | 2450 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2451 | #define _V7_DESC_PRESERVE_VALUE (1 << 8) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2453 | #define V7_PROP_ATTR_IS_WRITABLE(a) (!(a & V7_PROPERTY_NON_WRITABLE)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2454 | #define V7_PROP_ATTR_IS_ENUMERABLE(a) (!(a & V7_PROPERTY_NON_ENUMERABLE)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2455 | #define V7_PROP_ATTR_IS_CONFIGURABLE(a) (!(a & V7_PROPERTY_NON_CONFIGURABLE)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2457 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2458 | * Internal helpers for `V7_DESC_...` macros |
Marko Mikulicic |
0:c0ecb8bf28eb | 2459 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2460 | #define _V7_DESC_SHIFT 16 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2461 | #define _V7_DESC_MASK ((1 << _V7_DESC_SHIFT) - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2462 | #define _V7_MK_DESC(v, n) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2463 | (((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2464 | #define _V7_MK_DESC_INV(v, n) _V7_MK_DESC(!(v), (n)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2466 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2467 | * Property attribute descriptors that may be given to `v7_def()`: for each |
Marko Mikulicic |
0:c0ecb8bf28eb | 2468 | * attribute (`v7_prop_attr_t`), there is a corresponding macro, which takes |
Marko Mikulicic |
0:c0ecb8bf28eb | 2469 | * param: either 1 (set attribute) or 0 (clear attribute). If some particular |
Marko Mikulicic |
0:c0ecb8bf28eb | 2470 | * attribute isn't mentioned at all, it's left unchanged (or default, if the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2471 | * property is being created) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2472 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2473 | * There is additional flag: `V7_DESC_PRESERVE_VALUE`. If it is set, the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2474 | * property value isn't changed (or set to `undefined` if the property is being |
Marko Mikulicic |
0:c0ecb8bf28eb | 2475 | * created) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2476 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2477 | typedef unsigned long v7_prop_attr_desc_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2478 | #define V7_DESC_WRITABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2479 | #define V7_DESC_ENUMERABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2480 | #define V7_DESC_CONFIGURABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2481 | #define V7_DESC_GETTER(v) _V7_MK_DESC(v, V7_PROPERTY_GETTER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2482 | #define V7_DESC_SETTER(v) _V7_MK_DESC(v, V7_PROPERTY_SETTER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2483 | #define V7_DESC_PRESERVE_VALUE _V7_DESC_PRESERVE_VALUE |
Marko Mikulicic |
0:c0ecb8bf28eb | 2484 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2485 | #define _V7_DESC_HIDDEN(v) _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2486 | #define _V7_DESC_OFF_HEAP(v) _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2488 | /* See `v7_set_destructor_cb` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2489 | typedef void(v7_destructor_cb_t)(struct v7 *v7, void *ud); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2491 | /* Make an empty object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2492 | v7_val_t v7_mk_object(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2494 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2495 | * Returns true if the given value is an object or function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2496 | * i.e. it returns true if the value holds properties and can be |
Marko Mikulicic |
0:c0ecb8bf28eb | 2497 | * used as argument to `v7_get`, `v7_set` and `v7_def`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2498 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2499 | int v7_is_object(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2500 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2501 | /* Set object's prototype. Return old prototype or undefined on error. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2502 | v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2503 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2504 | /* Get object's prototype. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2505 | v7_val_t v7_get_proto(struct v7 *v7, v7_val_t obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2507 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2508 | * Lookup property `name` in object `obj`. If `obj` holds no such property, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2509 | * an `undefined` value is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2510 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2511 | * If `name_len` is ~0, `name` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 2512 | * `strlen(name)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2513 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2514 | v7_val_t v7_get(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2515 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2516 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2517 | * Like `v7_get()`, but "returns" value through `res` pointer argument. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2518 | * `res` must not be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2519 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2520 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 2521 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2522 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2523 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 2524 | enum v7_err v7_get_throwing(struct v7 *v7, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2525 | size_t name_len, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2527 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2528 | * Define object property, similar to JavaScript `Object.defineProperty()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2529 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2530 | * `name`, `name_len` specify property name, `val` is a property value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2531 | * `attrs_desc` is a set of flags which can affect property's attributes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2532 | * see comment of `v7_prop_attr_desc_t` for details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2533 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2534 | * If `name_len` is ~0, `name` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 2535 | * `strlen(name)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2536 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2537 | * Returns non-zero on success, 0 on error (e.g. out of memory). |
Marko Mikulicic |
0:c0ecb8bf28eb | 2538 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2539 | * See also `v7_set()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2540 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2541 | int v7_def(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2542 | v7_prop_attr_desc_t attrs_desc, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2544 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2545 | * Set object property. Behaves just like JavaScript assignment. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2546 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2547 | * See also `v7_def()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2548 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2549 | int v7_set(struct v7 *v7, v7_val_t obj, const char *name, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2550 | v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2552 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2553 | * A helper function to define object's method backed by a C function `func`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2554 | * `name` must be NUL-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2555 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2556 | * Return value is the same as for `v7_set()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2557 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2558 | int v7_set_method(struct v7 *, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2559 | v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2561 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2562 | * Delete own property `name` of the object `obj`. Does not follow the |
Marko Mikulicic |
0:c0ecb8bf28eb | 2563 | * prototype chain. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2564 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2565 | * If `name_len` is ~0, `name` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 2566 | * `strlen(name)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2567 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2568 | * Returns 0 on success, -1 on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2569 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2570 | int v7_del(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2572 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 2573 | struct prop_iter_proxy_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2574 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2576 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2577 | * Context for property iteration, see `v7_next_prop()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2578 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2579 | * Clients should not interpret contents of this structure, it's here merely to |
Marko Mikulicic |
0:c0ecb8bf28eb | 2580 | * allow clients to allocate it not from the heap. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2581 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2582 | struct prop_iter_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2583 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 2584 | struct prop_iter_proxy_ctx *proxy_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2585 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2586 | struct v7_property *cur_prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2587 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2588 | unsigned init : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2589 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2591 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2592 | * Initialize the property iteration context `ctx`, see `v7_next_prop()` for |
Marko Mikulicic |
0:c0ecb8bf28eb | 2593 | * usage example. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2594 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2595 | enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2596 | struct prop_iter_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2597 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2598 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2599 | * Destruct the property iteration context `ctx`, see `v7_next_prop()` for |
Marko Mikulicic |
0:c0ecb8bf28eb | 2600 | * usage example |
Marko Mikulicic |
0:c0ecb8bf28eb | 2601 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2602 | void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2604 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2605 | * Iterate over the `obj`'s properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2606 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2607 | * Usage example (here we assume we have some `v7_val_t obj`): |
Marko Mikulicic |
0:c0ecb8bf28eb | 2608 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2609 | * struct prop_iter_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2610 | * v7_val_t name, val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2611 | * v7_prop_attr_t attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2612 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2613 | * v7_init_prop_iter_ctx(v7, obj, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2614 | * while (v7_next_prop(v7, &ctx, &name, &val, &attrs)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2615 | * if (V7_PROP_ATTR_IS_ENUMERABLE(attrs)) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2616 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 2617 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2618 | * v7_destruct_prop_iter_ctx(v7, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2619 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2620 | * As you see, v7_next_prop will iterate through all properties, including |
Marko Mikulicic |
0:c0ecb8bf28eb | 2621 | * non-enumerable ones, and it's your responsibility to test the attributes |
Marko Mikulicic |
0:c0ecb8bf28eb | 2622 | * with the provided `V7_PROP_ATTR_*` macros and proceed as you see fit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2623 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2624 | int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2625 | v7_val_t *value, v7_prop_attr_t *attrs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2627 | /* Returns true if the object is an instance of a given constructor. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2628 | int v7_is_instanceof(struct v7 *v7, v7_val_t o, const char *c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2630 | /* Returns true if the object is an instance of a given constructor. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2631 | int v7_is_instanceof_v(struct v7 *v7, v7_val_t o, v7_val_t c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2633 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2634 | * Associates an opaque C value (anything that can be casted to a `void * ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2635 | * with an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2636 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2637 | * You can achieve a similar effect by just setting a special property with |
Marko Mikulicic |
0:c0ecb8bf28eb | 2638 | * a foreign value (see `v7_mk_foreign`), except user data offers the following |
Marko Mikulicic |
0:c0ecb8bf28eb | 2639 | * advantages: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2640 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2641 | * 1. You don't have to come up with some arbitrary "special" property name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2642 | * 2. JS scripts cannot access user data by mistake via property lookup. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2643 | * 3. The user data is available to the destructor. When the desctructor is |
Marko Mikulicic |
0:c0ecb8bf28eb | 2644 | * invoked you cannot access any of its properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2645 | * 4. Allows the implementation to use a more compact encoding |
Marko Mikulicic |
0:c0ecb8bf28eb | 2646 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2647 | * Does nothing if `obj` is not a mutable object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2648 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2649 | void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2651 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2652 | * Get the opaque user data set with `v7_set_user_data`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2653 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2654 | * Returns NULL if there is no user data set or if `obj` is not an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2655 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2656 | void *v7_get_user_data(struct v7 *v7, v7_val_t obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2657 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2658 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2659 | * Register a callback which will be invoked when a given object gets |
Marko Mikulicic |
0:c0ecb8bf28eb | 2660 | * reclaimed by the garbage collector. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2661 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2662 | * The callback will be invoked while garbage collection is still in progress |
Marko Mikulicic |
0:c0ecb8bf28eb | 2663 | * and hence the internal state of the JS heap is in an undefined state. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2664 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2665 | * The only v7 API which is safe to use in this callback is `v7_disown()`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2666 | * that's why `v7` pointer is given to it. *Calls to any other v7 functions are |
Marko Mikulicic |
0:c0ecb8bf28eb | 2667 | * illegal here*. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2668 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2669 | * The intended use case is to reclaim resources allocated by C code. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2670 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2671 | void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2673 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2674 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2675 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2676 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2677 | #endif /* CS_V7_SRC_OBJECT_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2678 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2679 | #line 1 "v7/src/tokenizer.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2680 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2681 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2682 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2683 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2684 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2686 | #ifndef CS_V7_SRC_TOKENIZER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2687 | #define CS_V7_SRC_TOKENIZER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2689 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2690 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2691 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2693 | enum v7_tok { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2694 | TOK_END_OF_INPUT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2695 | TOK_NUMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2696 | TOK_STRING_LITERAL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2697 | TOK_REGEX_LITERAL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2698 | TOK_IDENTIFIER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2700 | /* Punctuators */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2701 | TOK_OPEN_CURLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2702 | TOK_CLOSE_CURLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2703 | TOK_OPEN_PAREN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2704 | TOK_CLOSE_PAREN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2705 | TOK_COMMA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2706 | TOK_OPEN_BRACKET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2707 | TOK_CLOSE_BRACKET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2708 | TOK_DOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2709 | TOK_COLON, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2710 | TOK_SEMICOLON, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2711 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2712 | /* Equality ops, in this order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2713 | TOK_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2714 | TOK_EQ_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2715 | TOK_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2716 | TOK_NE_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2717 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2718 | /* Assigns */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2719 | TOK_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2720 | TOK_REM_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2721 | TOK_MUL_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2722 | TOK_DIV_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2723 | TOK_XOR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2724 | TOK_PLUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2725 | TOK_MINUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2726 | TOK_OR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2727 | TOK_AND_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2728 | TOK_LSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2729 | TOK_RSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2730 | TOK_URSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2731 | TOK_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2732 | TOK_LOGICAL_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2733 | TOK_PLUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2734 | TOK_MINUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2735 | TOK_PLUS_PLUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2736 | TOK_MINUS_MINUS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2737 | TOK_LOGICAL_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2738 | TOK_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2739 | TOK_QUESTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2740 | TOK_TILDA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2741 | TOK_REM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2742 | TOK_MUL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2743 | TOK_DIV, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2744 | TOK_XOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2746 | /* Relational ops, must go in this order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2747 | TOK_LE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2748 | TOK_LT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2749 | TOK_GE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2750 | TOK_GT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2751 | TOK_LSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2752 | TOK_RSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2753 | TOK_URSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2754 | TOK_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2756 | /* Keywords. must be in the same order as tokenizer.c::s_keywords array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2757 | TOK_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2758 | TOK_CASE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2759 | TOK_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2760 | TOK_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2761 | TOK_DEBUGGER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2762 | TOK_DEFAULT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2763 | TOK_DELETE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2764 | TOK_DO, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2765 | TOK_ELSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2766 | TOK_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2767 | TOK_FINALLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2768 | TOK_FOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2769 | TOK_FUNCTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2770 | TOK_IF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2771 | TOK_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2772 | TOK_INSTANCEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2773 | TOK_NEW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2774 | TOK_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2775 | TOK_RETURN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2776 | TOK_SWITCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2777 | TOK_THIS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2778 | TOK_THROW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2779 | TOK_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2780 | TOK_TRY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2781 | TOK_TYPEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2782 | TOK_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2783 | TOK_VOID, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2784 | TOK_WHILE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2785 | TOK_WITH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2786 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2787 | /* TODO(lsm): process these reserved words too */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2788 | TOK_CLASS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2789 | TOK_ENUM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2790 | TOK_EXTENDS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2791 | TOK_SUPER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2792 | TOK_CONST, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2793 | TOK_EXPORT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2794 | TOK_IMPORT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2795 | TOK_IMPLEMENTS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2796 | TOK_LET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2797 | TOK_PRIVATE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2798 | TOK_PUBLIC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2799 | TOK_INTERFACE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2800 | TOK_PACKAGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2801 | TOK_PROTECTED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2802 | TOK_STATIC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2803 | TOK_YIELD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2804 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2805 | NUM_TOKENS |
Marko Mikulicic |
0:c0ecb8bf28eb | 2806 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 2807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2808 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2809 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2810 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2812 | V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2813 | V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2814 | enum v7_tok prev_tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2815 | V7_PRIVATE int is_reserved_word_token(enum v7_tok tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 2816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2817 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2818 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 2819 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2821 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2823 | #endif /* CS_V7_SRC_TOKENIZER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2824 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 2825 | #line 1 "v7/src/opcodes.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 2826 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 2827 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2828 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 2829 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 2830 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2831 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2832 | #ifndef CS_V7_SRC_OPCODES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2833 | #define CS_V7_SRC_OPCODES_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2835 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2836 | * ==== Instructions |
Marko Mikulicic |
0:c0ecb8bf28eb | 2837 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2838 | * Bytecode instructions consist of 1-byte opcode, optionally followed by N |
Marko Mikulicic |
0:c0ecb8bf28eb | 2839 | * bytes of arguments. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2840 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2841 | * Opcodes that accept an index in the literal table (PUSH_LIT, GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2842 | * SET_VAR, ...) also accept inline literals. In order to distinguish indices in |
Marko Mikulicic |
0:c0ecb8bf28eb | 2843 | * the literals table and the inline literals, indices 0 and 1 are reserved as |
Marko Mikulicic |
0:c0ecb8bf28eb | 2844 | * type tags for inline literals: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2845 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2846 | * if 0, the following bytes encode a string literal |
Marko Mikulicic |
0:c0ecb8bf28eb | 2847 | * if 1, they encode a number (textual, like in the AST) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2848 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2849 | * (see enum bcode_inline_lit_type_tag) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2850 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2851 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2852 | * Stack diagrams follow the syntax and semantics of: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2853 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2854 | * http://everything2.com/title/Forth+stack+diagrams[Forth stack diagrams]. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2855 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2856 | * We use the following extension in the terminology: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2857 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2858 | * `T`: "Try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 2859 | * `A`: opcode arguments. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2860 | * `S`: stash register (one element stack). |
Marko Mikulicic |
0:c0ecb8bf28eb | 2861 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2862 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2863 | enum opcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 2864 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2865 | * Removes an item from the top of the stack. It is undefined what happens if |
Marko Mikulicic |
0:c0ecb8bf28eb | 2866 | * the stack is empty. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2867 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2868 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2869 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2870 | OP_DROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2871 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2872 | * Duplicates a value on top of the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2873 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2874 | * `( a -- a a)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2875 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2876 | OP_DUP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2877 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2878 | * Duplicates 2 values from the top of the stack in the same order. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2879 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2880 | * `( a b -- a b a b)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2881 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2882 | OP_2DUP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2883 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2884 | * Swap the top two items on the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2885 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2886 | * `( a b -- b a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2887 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2888 | OP_SWAP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2889 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2890 | * Copy current top of the stack to the temporary stash register. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2891 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2892 | * The content of the stash register will be cleared in the event of an |
Marko Mikulicic |
0:c0ecb8bf28eb | 2893 | * exception. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2894 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2895 | * `( a S: b -- a S: a)` saves TOS to stash reg |
Marko Mikulicic |
0:c0ecb8bf28eb | 2896 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2897 | OP_STASH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2898 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2899 | * Replace the top of the stack with the content of the temporary stash |
Marko Mikulicic |
0:c0ecb8bf28eb | 2900 | * register. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2901 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2902 | * The stash register is cleared afterwards. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2903 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2904 | * `( a S: b -- b S: nil )` replaces tos with stash reg |
Marko Mikulicic |
0:c0ecb8bf28eb | 2905 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2906 | OP_UNSTASH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2907 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2908 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2909 | * Effectively drops the last-but-one element from stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 2910 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2911 | * `( a b -- b )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2912 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2913 | OP_SWAP_DROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2915 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2916 | * Pushes `undefined` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2917 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2918 | * `( -- undefined )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2919 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2920 | OP_PUSH_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2921 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2922 | * Pushes `null` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2923 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2924 | * `( -- null )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2925 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2926 | OP_PUSH_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2927 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2928 | * Pushes current value of `this` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2929 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2930 | * `( -- this )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2931 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2932 | OP_PUSH_THIS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2933 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2934 | * Pushes `true` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2935 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2936 | * `( -- true )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2937 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2938 | OP_PUSH_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2939 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2940 | * Pushes `false` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2941 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2942 | * `( -- false )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2943 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2944 | OP_PUSH_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2945 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2946 | * Pushes `0` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2947 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2948 | * `( -- 0 )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2949 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2950 | OP_PUSH_ZERO, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2951 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2952 | * Pushes `1` onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2953 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2954 | * `( -- 1 )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2955 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2956 | OP_PUSH_ONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2957 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2958 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2959 | * Pushes a value from literals table onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2960 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2961 | * The opcode takes a varint operand interpreted as an index in the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 2962 | * literal table (see lit table). |
Marko Mikulicic |
0:c0ecb8bf28eb | 2963 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2964 | * ( -- a ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 2965 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2966 | OP_PUSH_LIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2968 | OP_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2969 | OP_LOGICAL_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2971 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2972 | * Takes a number from the top of the stack, inverts the sign and pushes it |
Marko Mikulicic |
0:c0ecb8bf28eb | 2973 | * back. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2974 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2975 | * `( a -- -a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2976 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2977 | OP_NEG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2978 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2979 | * Takes a number from the top of the stack pushes the evaluation of |
Marko Mikulicic |
0:c0ecb8bf28eb | 2980 | * `Number()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2981 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2982 | * `( a -- Number(a) )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 2983 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 2984 | OP_POS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 2985 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 2986 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 2987 | * Takes 2 values from the top of the stack and performs addition operation: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2988 | * If any of the two values is not `undefined`, number or boolean, both values |
Marko Mikulicic |
0:c0ecb8bf28eb | 2989 | * are converted into strings and concatenated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2990 | * Otherwise, both values are treated as numbers: |
Marko Mikulicic |
0:c0ecb8bf28eb | 2991 | * * `undefined` is converted into NaN |
Marko Mikulicic |
0:c0ecb8bf28eb | 2992 | * * `true` is converted into 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2993 | * * `false` is converted into 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 2994 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2995 | * Result is pushed back onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2996 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2997 | * TODO: make it behave exactly like JavaScript's `+` operator. |
Marko Mikulicic |
0:c0ecb8bf28eb | 2998 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 2999 | * `( a b -- a+b )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3000 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3001 | OP_ADD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3002 | OP_SUB, /* ( a b -- a-b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3003 | OP_REM, /* ( a b -- a%b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3004 | OP_MUL, /* ( a b -- a*b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3005 | OP_DIV, /* ( a b -- a/b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3006 | OP_LSHIFT, /* ( a b -- a<<b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3007 | OP_RSHIFT, /* ( a b -- a>>b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3008 | OP_URSHIFT, /* ( a b -- a>>>b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3009 | OP_OR, /* ( a b -- a|b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3010 | OP_XOR, /* ( a b -- a^b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3011 | OP_AND, /* ( a b -- a&b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3013 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3014 | * Takes two numbers form the top of the stack and pushes `true` if they are |
Marko Mikulicic |
0:c0ecb8bf28eb | 3015 | * equal, or `false` if they are not equal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3016 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3017 | * ( a b -- a===b ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3018 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3019 | OP_EQ_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3020 | OP_EQ, /* ( a b -- a==b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3021 | OP_NE, /* ( a b -- a!=b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3022 | OP_NE_NE, /* ( a b -- a!==b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3023 | OP_LT, /* ( a b -- a<b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3024 | OP_LE, /* ( a b -- a<=b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3025 | OP_GT, /* ( a b -- a>b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3026 | OP_GE, /* ( a b -- a>=b ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3027 | OP_INSTANCEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3029 | OP_TYPEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3031 | OP_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3032 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3033 | * Takes 2 values from the stack, treats the top of the stack as property name |
Marko Mikulicic |
0:c0ecb8bf28eb | 3034 | * and the next value must be an object, an array or a string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3035 | * If it's an object, pushes the value of its named property onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3036 | * If it's an array or a string, returns a value at a given position. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3037 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3038 | OP_GET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3039 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3040 | * Takes 3 items from the stack: value, property name, object. Sets the given |
Marko Mikulicic |
0:c0ecb8bf28eb | 3041 | * property of a given object to a given value, pushes value back onto the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3042 | *stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3043 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3044 | * `( a b c -- a[b]=c )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3045 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3046 | OP_SET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3047 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3048 | * Takes 1 value from the stack and a varint argument -- index of the var name |
Marko Mikulicic |
0:c0ecb8bf28eb | 3049 | * in the literals table. Tries to find the variable in the current scope |
Marko Mikulicic |
0:c0ecb8bf28eb | 3050 | * chain and assign the value to it. If the varialble is not found -- creates |
Marko Mikulicic |
0:c0ecb8bf28eb | 3051 | * a new one in the global scope. Pushes the value back to the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3052 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3053 | * `( a -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3054 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3055 | OP_SET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3056 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3057 | * Takes a varint argument -- index of the var name in the literals table. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3058 | * Looks up that variable in the scope chain and pushes its value onto the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3059 | * stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3060 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3061 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3062 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3063 | OP_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3065 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3066 | * Like OP_GET_VAR but returns undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 3067 | * instead of throwing reference error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3068 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3069 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3070 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3071 | OP_SAFE_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3073 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3074 | * ==== Jumps |
Marko Mikulicic |
0:c0ecb8bf28eb | 3075 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3076 | * All jump instructions take one 4-byte argument: offset to jump to. Offset |
Marko Mikulicic |
0:c0ecb8bf28eb | 3077 | *is a |
Marko Mikulicic |
0:c0ecb8bf28eb | 3078 | * index of the byte in the instruction stream, starting with 0. No byte order |
Marko Mikulicic |
0:c0ecb8bf28eb | 3079 | * conversion is applied. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3080 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3081 | * TODO: specify byte order for the offset. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3082 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3084 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3085 | * Unconditiona jump. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3086 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3087 | OP_JMP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3088 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3089 | * Takes one value from the stack and performs a jump if conversion of that |
Marko Mikulicic |
0:c0ecb8bf28eb | 3090 | * value to boolean results in `true`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3091 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3092 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3093 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3094 | OP_JMP_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3095 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3096 | * Takes one value from the stack and performs a jump if conversion of that |
Marko Mikulicic |
0:c0ecb8bf28eb | 3097 | * value to boolean results in `false`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3098 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3099 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3100 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3101 | OP_JMP_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3102 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3103 | * Like OP_JMP_TRUE but if the branch |
Marko Mikulicic |
0:c0ecb8bf28eb | 3104 | * is taken it also drops another stack element: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3105 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3106 | * if `b` is true: `( a b -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3107 | * if `b` is false: `( a b -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3108 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3109 | OP_JMP_TRUE_DROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3110 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3111 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3112 | * Conditional jump on the v7->is_continuing flag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3113 | * Clears the flag once executed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3114 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3115 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3116 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3117 | OP_JMP_IF_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3118 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3119 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3120 | * Constructs a new empty object and pushes it onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3121 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3122 | * `( -- {} )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3123 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3124 | OP_CREATE_OBJ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3125 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3126 | * Constructs a new empty array and pushes it onto the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3127 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3128 | * `( -- [] )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3129 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3130 | OP_CREATE_ARR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3132 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3133 | * Allocates the iteration context (for `OP_NEXT_PROP`) from heap and pushes |
Marko Mikulicic |
0:c0ecb8bf28eb | 3134 | * a foreign pointer to it on stack. The allocated data is stored as "user |
Marko Mikulicic |
0:c0ecb8bf28eb | 3135 | * data" of the object, and it will be reclaimed automatically when the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3136 | * object gets garbage-collected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3137 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3138 | * `( -- ctx )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3139 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3140 | OP_PUSH_PROP_ITER_CTX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3142 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3143 | * Yields the next property name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3144 | * Used in the for..in construct. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3145 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3146 | * The first evaluation must receive `null` as handle. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3147 | * Subsequent evaluations will either: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3148 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3149 | * a) produce a new handle, the key and true value: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3150 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3151 | * `( o h -- o h' key true)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3152 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3153 | * b) produce a false value only, indicating no more properties: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3154 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3155 | * `( o h -- false)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3156 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3157 | OP_NEXT_PROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3159 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3160 | * Copies the function object at TOS and assigns current scope |
Marko Mikulicic |
0:c0ecb8bf28eb | 3161 | * in func->scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3162 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3163 | * `( a -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3164 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3165 | OP_FUNC_LIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3166 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3167 | * Takes the number of arguments as parameter. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3168 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3169 | * Pops N function arguments from stack, then pops function, then pops `this`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3170 | * Calls a function and populates TOS with the returned value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3171 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3172 | * `( this f a0 a1 ... aN -- f(a0,a1,...) )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3173 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3174 | OP_CALL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3175 | OP_NEW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3176 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3177 | * Checks that TOS is a callable and if not saves an exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 3178 | * that will will be thrown by CALL after all arguments have been evaluated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3179 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3180 | OP_CHECK_CALL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3181 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3182 | * Returns the current function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3183 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3184 | * It has no stack side effects. The function upon return will leave the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3185 | * return value on the stack. The return value must be pushed on the stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 3186 | * prior to invoking a RET. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3187 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3188 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3189 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3190 | OP_RET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3192 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3193 | * Deletes the property of given name `p` from the given object `o`. Returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 3194 | * boolean value `a`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3195 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3196 | * `( o p -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3197 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3198 | OP_DELETE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3199 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3200 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3201 | * Like `OP_DELETE`, but uses the current scope as an object to delete |
Marko Mikulicic |
0:c0ecb8bf28eb | 3202 | * a property from. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3203 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3204 | * `( p -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3205 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3206 | OP_DELETE_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3207 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3208 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3209 | * Pushes a value (bcode offset of `catch` block) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3210 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3211 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3212 | * Used in the beginning of the `try` block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3213 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3214 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3215 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3216 | OP_TRY_PUSH_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3218 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3219 | * Pushes a value (bcode offset of `finally` block) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3220 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3221 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3222 | * Used in the beginning of the `try` block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3223 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3224 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3225 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3226 | * TODO: implement me |
Marko Mikulicic |
0:c0ecb8bf28eb | 3227 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3228 | OP_TRY_PUSH_FINALLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3229 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3230 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3231 | * Pushes a value (bcode offset of a label) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3232 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3233 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3234 | * Used at the beginning of loops that contain break or continue. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3235 | * Possible optimisation: don't emit if we can ensure that no break or |
Marko Mikulicic |
0:c0ecb8bf28eb | 3236 | * continue statement is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3237 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3238 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3239 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3240 | OP_TRY_PUSH_LOOP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3242 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3243 | * Pushes a value (bcode offset of a label) from opcode argument to |
Marko Mikulicic |
0:c0ecb8bf28eb | 3244 | * "try stack". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3245 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3246 | * Used at the beginning of switch statements. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3247 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3248 | * `( A: a -- T: a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3249 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3250 | OP_TRY_PUSH_SWITCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3252 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3253 | * Pops a value (bcode offset of `finally` or `catch` block) from "try |
Marko Mikulicic |
0:c0ecb8bf28eb | 3254 | * stack", and discards it |
Marko Mikulicic |
0:c0ecb8bf28eb | 3255 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3256 | * Used in the end of the `try` block, as well as in the beginning of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3257 | * `catch` and `finally` blocks |
Marko Mikulicic |
0:c0ecb8bf28eb | 3258 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3259 | * `( T: a -- T: )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3260 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3261 | OP_TRY_POP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3263 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3264 | * Used in the end of the `finally` block: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3265 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3266 | * - if some value is currently being thrown, keep throwing it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3267 | * If eventually we encounter `catch` block, the thrown value gets |
Marko Mikulicic |
0:c0ecb8bf28eb | 3268 | * populated on TOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3269 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3270 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3271 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3272 | * - if there is some pending value to return, keep returning it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3273 | * If we encounter no further `finally` blocks, then the returned value |
Marko Mikulicic |
0:c0ecb8bf28eb | 3274 | * gets populated on TOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3275 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3276 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3277 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3278 | * And return is performed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3279 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3280 | * - otherwise, do nothing |
Marko Mikulicic |
0:c0ecb8bf28eb | 3281 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3282 | OP_AFTER_FINALLY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3284 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3285 | * Throw value from TOS. First of all, it pops the value and saves it into |
Marko Mikulicic |
0:c0ecb8bf28eb | 3286 | * `v7->vals.thrown_error`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3287 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3288 | * `( a -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3289 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3290 | * Then unwinds stack looking for the first `catch` or `finally` blocks. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3291 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3292 | * - if `finally` is found, thrown value is kept into `v7->vals.thrown_error`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3293 | * - if `catch` is found, thrown value is pushed back to the stack: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3294 | * `( -- a )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3295 | * - otherwise, thrown value is kept into `v7->vals.thrown_error` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3296 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3297 | OP_THROW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3299 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3300 | * Unwind to next break entry in the try stack, evaluating |
Marko Mikulicic |
0:c0ecb8bf28eb | 3301 | * all finally blocks on its way up. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3302 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3303 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3304 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3305 | OP_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3307 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3308 | * Like OP_BREAK, but sets the v7->is_continuing flag |
Marko Mikulicic |
0:c0ecb8bf28eb | 3309 | * which will cause OP_JMP_IF_CONTINUE to restart the loop. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3310 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3311 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3312 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3313 | OP_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3315 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3316 | * Used when we enter the `catch` block. Takes a varint argument -- index of |
Marko Mikulicic |
0:c0ecb8bf28eb | 3317 | * the exception variable name in the literals table. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3318 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3319 | * Pops the exception value from the stack, creates a private frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3320 | * sets exception property on it with the given name. pushes this |
Marko Mikulicic |
0:c0ecb8bf28eb | 3321 | * private frame to call stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3322 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3323 | * `( e -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3324 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3325 | OP_ENTER_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3327 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3328 | * Ued when we exit from the `catch` block. Merely pops the private frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 3329 | * from the call stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3330 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3331 | * `( -- )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3332 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3333 | OP_EXIT_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3334 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3335 | OP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3336 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3338 | #define _OP_LINE_NO 0x80 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3340 | #endif /* CS_V7_SRC_OPCODES_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3341 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 3342 | #line 1 "v7/src/core.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 3343 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3344 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3345 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 3346 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 3347 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3348 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3349 | #ifndef CS_V7_SRC_CORE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3350 | #define CS_V7_SRC_CORE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3352 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3354 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3355 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3356 | /* Amalgamated: #include "v7/src/mm.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3357 | /* Amalgamated: #include "v7/src/parser.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3358 | /* Amalgamated: #include "v7/src/object_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3359 | /* Amalgamated: #include "v7/src/tokenizer.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3360 | /* Amalgamated: #include "v7/src/opcodes.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3362 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3363 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3364 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3366 | typedef uint64_t val_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3367 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3368 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3370 | typedef unsigned short entity_id_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3371 | typedef unsigned char entity_id_part_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3373 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3374 | * Magic numbers that are stored in various objects in order to identify their |
Marko Mikulicic |
0:c0ecb8bf28eb | 3375 | * type in runtime |
Marko Mikulicic |
0:c0ecb8bf28eb | 3376 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3377 | #define V7_ENTITY_ID_PROP 0xe9a1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3378 | #define V7_ENTITY_ID_PART_OBJ 0x57 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3379 | #define V7_ENTITY_ID_PART_GEN_OBJ 0x31 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3380 | #define V7_ENTITY_ID_PART_JS_FUNC 0x0d |
Marko Mikulicic |
0:c0ecb8bf28eb | 3381 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3382 | #define V7_ENTITY_ID_NONE 0xa5a5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3383 | #define V7_ENTITY_ID_PART_NONE 0xa5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3385 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3387 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3388 | * Double-precision floating-point number, IEEE 754 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3389 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3390 | * 64 bit (8 bytes) in total |
Marko Mikulicic |
0:c0ecb8bf28eb | 3391 | * 1 bit sign |
Marko Mikulicic |
0:c0ecb8bf28eb | 3392 | * 11 bits exponent |
Marko Mikulicic |
0:c0ecb8bf28eb | 3393 | * 52 bits mantissa |
Marko Mikulicic |
0:c0ecb8bf28eb | 3394 | * 7 6 5 4 3 2 1 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3395 | * seeeeeee|eeeemmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm |
Marko Mikulicic |
0:c0ecb8bf28eb | 3396 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3397 | * If an exponent is all-1 and mantissa is all-0, then it is an INFINITY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3398 | * 11111111|11110000|00000000|00000000|00000000|00000000|00000000|00000000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3399 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3400 | * If an exponent is all-1 and mantissa's MSB is 1, it is a quiet NaN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3401 | * 11111111|11111000|00000000|00000000|00000000|00000000|00000000|00000000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 3402 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3403 | * V7 NaN-packing: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3404 | * sign and exponent is 0xfff |
Marko Mikulicic |
0:c0ecb8bf28eb | 3405 | * 4 bits specify type (tag), must be non-zero |
Marko Mikulicic |
0:c0ecb8bf28eb | 3406 | * 48 bits specify value |
Marko Mikulicic |
0:c0ecb8bf28eb | 3407 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3408 | * 11111111|1111tttt|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv |
Marko Mikulicic |
0:c0ecb8bf28eb | 3409 | * NaN marker |type| 48-bit placeholder for values: pointers, strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 3410 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3411 | * On 64-bit platforms, pointers are really 48 bit only, so they can fit, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3412 | * provided they are sign extended |
Marko Mikulicic |
0:c0ecb8bf28eb | 3413 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3415 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3416 | * A tag is made of the sign bit and the 4 lower order bits of byte 6. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3417 | * So in total we have 32 possible tags. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3418 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3419 | * Tag (1,0) however cannot hold a zero payload otherwise it's interpreted as an |
Marko Mikulicic |
0:c0ecb8bf28eb | 3420 | * INFINITY; for simplicity we're just not going to use that combination. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3421 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3422 | #define MAKE_TAG(s, t) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3423 | ((uint64_t)(s) << 63 | (uint64_t) 0x7ff0 << 48 | (uint64_t)(t) << 48) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3425 | #define V7_TAG_OBJECT MAKE_TAG(1, 0xF) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3426 | #define V7_TAG_FOREIGN MAKE_TAG(1, 0xE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3427 | #define V7_TAG_UNDEFINED MAKE_TAG(1, 0xD) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3428 | #define V7_TAG_BOOLEAN MAKE_TAG(1, 0xC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3429 | #define V7_TAG_NAN MAKE_TAG(1, 0xB) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3430 | #define V7_TAG_STRING_I MAKE_TAG(1, 0xA) /* Inlined string len < 5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3431 | #define V7_TAG_STRING_5 MAKE_TAG(1, 0x9) /* Inlined string len 5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3432 | #define V7_TAG_STRING_O MAKE_TAG(1, 0x8) /* Owned string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3433 | #define V7_TAG_STRING_F MAKE_TAG(1, 0x7) /* Foreign string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3434 | #define V7_TAG_STRING_C MAKE_TAG(1, 0x6) /* String chunk */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3435 | #define V7_TAG_FUNCTION MAKE_TAG(1, 0x5) /* JavaScript function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3436 | #define V7_TAG_CFUNCTION MAKE_TAG(1, 0x4) /* C function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3437 | #define V7_TAG_STRING_D MAKE_TAG(1, 0x3) /* Dictionary string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3438 | #define V7_TAG_REGEXP MAKE_TAG(1, 0x2) /* Regex */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3439 | #define V7_TAG_NOVALUE MAKE_TAG(1, 0x1) /* Sentinel for no value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3440 | #define V7_TAG_MASK MAKE_TAG(1, 0xF) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3442 | #define _V7_NULL V7_TAG_FOREIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 3443 | #define _V7_UNDEFINED V7_TAG_UNDEFINED |
Marko Mikulicic |
0:c0ecb8bf28eb | 3444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3445 | V7_STATIC_ASSERT(_V7_NULL == V7_NULL, public_V7_NULL_is_wrong); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3446 | V7_STATIC_ASSERT(_V7_UNDEFINED == V7_UNDEFINED, public_V7_UNDEFINED_is_wrong); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3448 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3449 | * Object attributes bitmask |
Marko Mikulicic |
0:c0ecb8bf28eb | 3450 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3451 | typedef unsigned char v7_obj_attr_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3452 | #define V7_OBJ_NOT_EXTENSIBLE (1 << 0) /* TODO(lsm): store this in LSB */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3453 | #define V7_OBJ_DENSE_ARRAY (1 << 1) /* TODO(mkm): store in some tag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3454 | #define V7_OBJ_FUNCTION (1 << 2) /* function object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3455 | #define V7_OBJ_OFF_HEAP (1 << 3) /* object not managed by V7 HEAP */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3456 | #define V7_OBJ_HAS_DESTRUCTOR (1 << 4) /* has user data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3457 | #define V7_OBJ_PROXY (1 << 5) /* it's a Proxy object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3459 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3460 | * JavaScript value is either a primitive, or an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3461 | * There are 5 primitive types: Undefined, Null, Boolean, Number, String. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3462 | * Non-primitive type is an Object type. There are several classes of Objects, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3463 | * see description of `struct v7_generic_object` below for more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3464 | * This enumeration combines types and object classes in one enumeration. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3465 | * NOTE(lsm): compile with `-fshort-enums` to reduce sizeof(enum v7_type) to 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3466 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3467 | enum v7_type { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3468 | /* Primitive types */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3469 | V7_TYPE_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3470 | V7_TYPE_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3471 | V7_TYPE_BOOLEAN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3472 | V7_TYPE_NUMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3473 | V7_TYPE_STRING, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3474 | V7_TYPE_FOREIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3475 | V7_TYPE_CFUNCTION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3477 | /* Different classes of Object type */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3478 | V7_TYPE_GENERIC_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3479 | V7_TYPE_BOOLEAN_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3480 | V7_TYPE_STRING_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3481 | V7_TYPE_NUMBER_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3482 | V7_TYPE_FUNCTION_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3483 | V7_TYPE_CFUNCTION_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3484 | V7_TYPE_REGEXP_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3485 | V7_TYPE_ARRAY_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3486 | V7_TYPE_DATE_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3487 | V7_TYPE_ERROR_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3488 | V7_TYPE_MAX_OBJECT_TYPE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3489 | V7_NUM_TYPES |
Marko Mikulicic |
0:c0ecb8bf28eb | 3490 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3492 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3493 | * Call frame type mask: we have a "class hierarchy" of the call frames, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 3494 | * `struct v7_call_frame_base`, and the `type_mask` field represents the exact |
Marko Mikulicic |
0:c0ecb8bf28eb | 3495 | * frame type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3496 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3497 | * Possible values are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3498 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3499 | * - `V7_CALL_FRAME_MASK_PRIVATE | V7_CALL_FRAME_MASK_BCODE`: the most popular |
Marko Mikulicic |
0:c0ecb8bf28eb | 3500 | * frame type: call frame for bcode execution, either top-level code or JS |
Marko Mikulicic |
0:c0ecb8bf28eb | 3501 | * function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3502 | * - `V7_CALL_FRAME_MASK_PRIVATE`: used for `catch` clauses only: the variables |
Marko Mikulicic |
0:c0ecb8bf28eb | 3503 | * we create in `catch` clause should not be visible from the outside of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3504 | * clause, so we have to create a separate scope object for it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3505 | * - `V7_CALL_FRAME_MASK_CFUNC`: call frame for C function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3506 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3507 | typedef uint8_t v7_call_frame_mask_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3508 | #define V7_CALL_FRAME_MASK_BCODE (1 << 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3509 | #define V7_CALL_FRAME_MASK_PRIVATE (1 << 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3510 | #define V7_CALL_FRAME_MASK_CFUNC (1 << 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3512 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3513 | * Base of the call frame; includes the pointer to the previous frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3514 | * and the frame type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3515 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3516 | * In order to save memory, it also contains some bitfields which actually |
Marko Mikulicic |
0:c0ecb8bf28eb | 3517 | * belong to some "sub-structures". |
Marko Mikulicic |
0:c0ecb8bf28eb | 3518 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3519 | * The hierarchy is as follows: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3520 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3521 | * - v7_call_frame_base |
Marko Mikulicic |
0:c0ecb8bf28eb | 3522 | * - v7_call_frame_private |
Marko Mikulicic |
0:c0ecb8bf28eb | 3523 | * - v7_call_frame_bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3524 | * - v7_call_frame_cfunc |
Marko Mikulicic |
0:c0ecb8bf28eb | 3525 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3526 | struct v7_call_frame_base { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3527 | struct v7_call_frame_base *prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3529 | /* See comment for `v7_call_frame_mask_t` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3530 | v7_call_frame_mask_t type_mask : 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3532 | /* Belongs to `struct v7_call_frame_private` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3533 | unsigned int line_no : 16; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3535 | /* Belongs to `struct v7_call_frame_bcode` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3536 | unsigned is_constructor : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3538 | /* Belongs to `struct v7_call_frame_bcode` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3539 | unsigned int is_thrown : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3540 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3542 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3543 | * "private" call frame, used in `catch` blocks, merely for using a separate |
Marko Mikulicic |
0:c0ecb8bf28eb | 3544 | * scope object there. It is also a "base class" for the bcode call frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3545 | * see `struct v7_call_frame_bcode`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3546 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3547 | * TODO(dfrank): probably implement it differently, so that we can get rid of |
Marko Mikulicic |
0:c0ecb8bf28eb | 3548 | * the separate "private" frames whatsoever (and just include it into struct |
Marko Mikulicic |
0:c0ecb8bf28eb | 3549 | * v7_call_frame_bcode ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3550 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3551 | struct v7_call_frame_private { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3552 | struct v7_call_frame_base base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3553 | size_t stack_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3554 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3555 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3556 | * Current execution scope. Initially, it is equal to the `global_object`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3557 | * and at each function call, it is augmented by the new scope object, which |
Marko Mikulicic |
0:c0ecb8bf28eb | 3558 | * has the previous value as a prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3559 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3560 | val_t scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3562 | val_t try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3563 | } vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3564 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3565 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3566 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3567 | * "bcode" call frame, augments "private" frame with `bcode` and the position |
Marko Mikulicic |
0:c0ecb8bf28eb | 3568 | * in it, and `this` object. It is the primary frame type, used when executing |
Marko Mikulicic |
0:c0ecb8bf28eb | 3569 | * a bcode script or calling a function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3570 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3571 | struct v7_call_frame_bcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3572 | struct v7_call_frame_private base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3573 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3574 | val_t this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3575 | val_t thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3576 | } vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3577 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3578 | char *bcode_ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3579 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3581 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3582 | * "cfunc" call frame, used when calling cfunctions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3583 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3584 | struct v7_call_frame_cfunc { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3585 | struct v7_call_frame_base base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3586 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3587 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3588 | val_t this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3589 | } vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3591 | v7_cfunction_t *cfunc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3592 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3594 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3595 | * This structure groups together all val_t logical members |
Marko Mikulicic |
0:c0ecb8bf28eb | 3596 | * of struct v7 so that GC and freeze logic can easily access all |
Marko Mikulicic |
0:c0ecb8bf28eb | 3597 | * of them together. This structure must contain only val_t members. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3598 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3599 | struct v7_vals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3600 | val_t global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3601 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3602 | val_t arguments; /* arguments of current call */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3604 | val_t object_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3605 | val_t array_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3606 | val_t boolean_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3607 | val_t error_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3608 | val_t string_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3609 | val_t regexp_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3610 | val_t number_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3611 | val_t date_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3612 | val_t function_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3613 | val_t proxy_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3615 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3616 | * temporary register for `OP_STASH` and `OP_UNSTASH` instructions. Valid if |
Marko Mikulicic |
0:c0ecb8bf28eb | 3617 | * `v7->is_stashed` is non-zero |
Marko Mikulicic |
0:c0ecb8bf28eb | 3618 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3619 | val_t stash; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3620 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3621 | val_t error_objects[ERROR_CTOR_MAX]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3623 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3624 | * Value that is being thrown. Valid if `is_thrown` is non-zero (see below) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3625 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3626 | val_t thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3627 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3628 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3629 | * value that is going to be returned. Needed when some `finally` block needs |
Marko Mikulicic |
0:c0ecb8bf28eb | 3630 | * to be executed after `return my_value;` was issued. Used in bcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3631 | * See also `is_returned` below |
Marko Mikulicic |
0:c0ecb8bf28eb | 3632 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3633 | val_t returned_value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3634 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3635 | val_t last_name[2]; /* used for error reporting */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3636 | /* most recent OP_CHECK_CALL exceptions, to be thrown by OP_CALL|OP_NEW */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3637 | val_t call_check_ex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3638 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3640 | struct v7 { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3641 | struct v7_vals vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3643 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3644 | * Stack of call frames. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3645 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3646 | * Execution contexts are contained in two chains: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3647 | * - Stack of call frames: to allow returning, throwing, and stack trace |
Marko Mikulicic |
0:c0ecb8bf28eb | 3648 | * generation; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3649 | * - In the lexical scope via their prototype chain (to allow variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 3650 | * lookup), see `struct v7_call_frame_private::scope`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3651 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3652 | * Execution contexts should be allocated on heap, because they might not be |
Marko Mikulicic |
0:c0ecb8bf28eb | 3653 | * on a call stack but still referenced (closures). |
Marko Mikulicic |
0:c0ecb8bf28eb | 3654 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3655 | * New call frame is created every time some top-level code is evaluated, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3656 | * or some code is being `eval`-d, or some function is called, either JS |
Marko Mikulicic |
0:c0ecb8bf28eb | 3657 | * function or C function (although the call frame types are different for |
Marko Mikulicic |
0:c0ecb8bf28eb | 3658 | * JS functions and cfunctions, see `struct v7_call_frame_base` and its |
Marko Mikulicic |
0:c0ecb8bf28eb | 3659 | * sub-structures) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3660 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3661 | * When no code is being evaluated at the moment, `call_stack` is `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3662 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3663 | * See comment for `struct v7_call_frame_base` for some more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3664 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3665 | struct v7_call_frame_base *call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3667 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3668 | * Bcode executes until it reaches `bottom_call_frame`. When some top-level |
Marko Mikulicic |
0:c0ecb8bf28eb | 3669 | * or `eval`-d code starts execution, the `bottom_call_frame` is set to the |
Marko Mikulicic |
0:c0ecb8bf28eb | 3670 | * call frame which was just created for the execution. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3671 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3672 | struct v7_call_frame_base *bottom_call_frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3674 | struct mbuf stack; /* value stack for bcode interpreter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3675 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3676 | struct mbuf owned_strings; /* Sequence of (varint len, char data[]) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3677 | struct mbuf foreign_strings; /* Sequence of (varint len, char *data) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3679 | struct mbuf tmp_stack; /* Stack of val_t* elements, used as root set */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3680 | int need_gc; /* Set to true to trigger GC when safe */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3682 | struct gc_arena generic_object_arena; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3683 | struct gc_arena function_arena; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3684 | struct gc_arena property_arena; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3685 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 3686 | size_t function_arena_ast_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3687 | size_t bcode_ops_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3688 | size_t bcode_lit_total_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3689 | size_t bcode_lit_deser_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3690 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3691 | struct mbuf owned_values; /* buffer for GC roots owned by C code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3693 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3694 | * Stack of the root bcodes being executed at the moment. Note that when some |
Marko Mikulicic |
0:c0ecb8bf28eb | 3695 | * regular JS function is called inside `eval_bcode()`, the function's bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3696 | * is NOT added here. Buf if some cfunction is called, which in turn calls |
Marko Mikulicic |
0:c0ecb8bf28eb | 3697 | * `b_exec()` (or `b_apply()`) recursively, the new bcode is added to this |
Marko Mikulicic |
0:c0ecb8bf28eb | 3698 | * stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3699 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3700 | struct mbuf act_bcodes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3702 | char error_msg[80]; /* Exception message */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3704 | struct mbuf json_visited_stack; /* Detecting cycle in to_json */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3706 | /* Parser state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3707 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3708 | struct v7_pstate pstate; /* Parsing state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3709 | enum v7_tok cur_tok; /* Current token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3710 | const char *tok; /* Parsed terminal token (ident, number, string) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3711 | unsigned long tok_len; /* Length of the parsed terminal token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3712 | size_t last_var_node; /* Offset of last var node or function/script node */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3713 | int after_newline; /* True if the cur_tok starts a new line */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3714 | double cur_tok_dbl; /* When tokenizing, parser stores TOK_NUMBER here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3716 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3717 | * Current linenumber. Currently it is used by parser, compiler and bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3718 | * evaluator. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3719 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3720 | * - Parser: it's the last line_no emitted to AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 3721 | * - Compiler: it's the last line_no emitted to bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 3722 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3723 | int line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3724 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3725 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3726 | /* singleton, pointer because of amalgamation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3727 | struct v7_property *cur_dense_prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3729 | volatile int interrupted; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3730 | #ifdef V7_STACK_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 3731 | void *sp_limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3732 | void *sp_lwm; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3733 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3735 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3736 | /* linked list of v7 contexts, needed by cyg_profile hooks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3737 | struct v7 *next_v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3739 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3740 | /* linked list of stack tracking contexts */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3741 | struct stack_track_ctx *stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3743 | int stack_stat[V7_STACK_STATS_CNT]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3744 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3746 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3748 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 3749 | struct mbuf malloc_trace; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3750 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3751 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3752 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3753 | * TODO(imax): remove V7_DISABLE_STR_ALLOC_SEQ knob after 2015/12/01 if there |
Marko Mikulicic |
0:c0ecb8bf28eb | 3754 | * are no issues. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3755 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3756 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3757 | uint16_t gc_next_asn; /* Next sequence number to use. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3758 | uint16_t gc_min_asn; /* Minimal sequence number currently in use. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3759 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3760 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3761 | #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3762 | size_t parser_stack_data_max_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3763 | size_t parser_stack_ret_max_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3764 | size_t parser_stack_data_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3765 | size_t parser_stack_ret_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3766 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3768 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 3769 | FILE *freeze_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3770 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3771 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3772 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3773 | * true if exception is currently being created. Needed to avoid recursive |
Marko Mikulicic |
0:c0ecb8bf28eb | 3774 | * exception creation |
Marko Mikulicic |
0:c0ecb8bf28eb | 3775 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3776 | unsigned int creating_exception : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3777 | /* while true, GC is inhibited */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3778 | unsigned int inhibit_gc : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3779 | /* true if `thrown_error` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3780 | unsigned int is_thrown : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3781 | /* true if `returned_value` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3782 | unsigned int is_returned : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3783 | /* true if a finally block is executing while breaking */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3784 | unsigned int is_breaking : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3785 | /* true when a continue OP is executed, reset by `OP_JMP_IF_CONTINUE` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3786 | unsigned int is_continuing : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3787 | /* true if some value is currently stashed (`v7->vals.stash`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3788 | unsigned int is_stashed : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3789 | /* true if last emitted statement does not affect data stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3790 | unsigned int is_stack_neutral : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3791 | /* true if precompiling; affects compiler bcode choices */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3792 | unsigned int is_precompiling : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3794 | enum opcode last_ops[2]; /* trace of last ops, used for error reporting */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3795 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3797 | struct v7_property { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3798 | struct v7_property * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3799 | next; /* Linkage in struct v7_generic_object::properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3800 | v7_prop_attr_t attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3801 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3802 | entity_id_t entity_id; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3803 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3804 | val_t name; /* Property name (a string) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3805 | val_t value; /* Property value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3806 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3808 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3809 | * "base object": structure which is shared between objects and functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3810 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3811 | struct v7_object { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3812 | /* First HIDDEN property in a chain is an internal object value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3813 | struct v7_property *properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3814 | v7_obj_attr_t attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3815 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3816 | entity_id_part_t entity_id_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3817 | entity_id_part_t entity_id_spec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3818 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3819 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3821 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3822 | * An object is an unordered collection of properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3823 | * A function stored in a property of an object is called a method. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3824 | * A property has a name, a value, and set of attributes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3825 | * Attributes are: ReadOnly, DontEnum, DontDelete, Internal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3826 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3827 | * A constructor is a function that creates and initializes objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3828 | * Each constructor has an associated prototype object that is used for |
Marko Mikulicic |
0:c0ecb8bf28eb | 3829 | * inheritance and shared properties. When a constructor creates an object, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3830 | * the new object references the constructor’s prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3831 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3832 | * Objects could be a "generic objects" which is a collection of properties, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3833 | * or a "typed object" which also hold an internal value like String or Number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3834 | * Those values are implicit, unnamed properties of the respective types, |
Marko Mikulicic |
0:c0ecb8bf28eb | 3835 | * and can be coerced into primitive types by calling a respective constructor |
Marko Mikulicic |
0:c0ecb8bf28eb | 3836 | * as a function: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3837 | * var a = new Number(123); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3838 | * typeof(a) == 'object'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3839 | * typeof(Number(a)) == 'number'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3840 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3841 | struct v7_generic_object { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3842 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3843 | * This has to be the first field so that objects can be managed by the GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3844 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3845 | struct v7_object base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3846 | struct v7_object *prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3847 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3849 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3850 | * Variables are function-scoped and are hoisted. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3851 | * Lexical scoping & closures: each function has a chain of scopes, defined |
Marko Mikulicic |
0:c0ecb8bf28eb | 3852 | * by the lexicographic order of function definitions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3853 | * Scope is different from the execution context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3854 | * Execution context carries "variable object" which is variable/value |
Marko Mikulicic |
0:c0ecb8bf28eb | 3855 | * mapping for all variables defined in a function, and `this` object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3856 | * If function is not called as a method, then `this` is a global object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3857 | * Otherwise, `this` is an object that contains called method. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3858 | * New execution context is created each time a function call is performed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3859 | * Passing arguments through recursion is done using execution context, e.g. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3860 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3861 | * var factorial = function(num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3862 | * return num < 2 ? 1 : num * factorial(num - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3863 | * }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3864 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3865 | * Here, recursion calls the same function `factorial` several times. Execution |
Marko Mikulicic |
0:c0ecb8bf28eb | 3866 | * contexts for each call form a stack. Each context has different variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 3867 | * object, `vars`, with different values of `num`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3868 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3869 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3870 | struct v7_js_function { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3871 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3872 | * Functions are objects. This has to be the first field so that function |
Marko Mikulicic |
0:c0ecb8bf28eb | 3873 | * objects can be managed by the GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3874 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3875 | struct v7_object base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3876 | struct v7_generic_object *scope; /* lexical scope of the closure */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3878 | /* bytecode, might be shared between functions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3879 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3880 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3882 | struct v7_regexp { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3883 | val_t regexp_string; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3884 | struct slre_prog *compiled_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3885 | long lastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3886 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3888 | /* Vector, describes some memory location pointed by `p` with length `len` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3889 | struct v7_vec { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3890 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3891 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3892 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3894 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3895 | * Constant vector, describes some const memory location pointed by `p` with |
Marko Mikulicic |
0:c0ecb8bf28eb | 3896 | * length `len` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3897 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3898 | struct v7_vec_const { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3899 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3900 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3901 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 3902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3903 | #define V7_VEC(str) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3904 | { (str), sizeof(str) - 1 } |
Marko Mikulicic |
0:c0ecb8bf28eb | 3905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3906 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3907 | * Returns current execution scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3908 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3909 | * See comment for `struct v7_call_frame_private::vals::scope` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3910 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3911 | V7_PRIVATE v7_val_t get_scope(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3913 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3914 | * Returns 1 if currently executing bcode in the "strict mode", 0 otherwise |
Marko Mikulicic |
0:c0ecb8bf28eb | 3915 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3916 | V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3918 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 3920 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3922 | #endif /* CS_V7_SRC_CORE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3923 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 3924 | #line 1 "v7/src/primitive_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 3925 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 3926 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3927 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 3928 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 3929 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3931 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3932 | * === Primitives |
Marko Mikulicic |
0:c0ecb8bf28eb | 3933 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3934 | * All primitive values but strings. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3935 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3936 | * "foreign" values are also here, see `v7_mk_foreign()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3937 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3939 | #ifndef CS_V7_SRC_PRIMITIVE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3940 | #define CS_V7_SRC_PRIMITIVE_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3942 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3944 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 3945 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 3946 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3948 | /* Make numeric primitive value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3949 | NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double num); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3950 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3951 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3952 | * Returns number value stored in `v7_val_t` as `double`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3953 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3954 | * Returns NaN for non-numbers. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3955 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3956 | NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3957 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3958 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3959 | * Returns number value stored in `v7_val_t` as `int`. If the number value is |
Marko Mikulicic |
0:c0ecb8bf28eb | 3960 | * not an integer, the fraction part will be discarded. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3961 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3962 | * If the given value is a non-number, or NaN, the result is undefined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3963 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3964 | NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3965 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3966 | /* Returns true if given value is a primitive number value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3967 | int v7_is_number(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3969 | /* Make boolean primitive value (either `true` or `false`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3970 | NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int is_true); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3971 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3972 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3973 | * Returns boolean stored in `v7_val_t`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 3974 | * 0 for `false` or non-boolean, non-0 for `true` |
Marko Mikulicic |
0:c0ecb8bf28eb | 3975 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3976 | NOINSTR int v7_get_bool(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3978 | /* Returns true if given value is a primitive boolean value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3979 | int v7_is_boolean(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3981 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3982 | * Make `null` primitive value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3983 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3984 | * NOTE: this function is deprecated and will be removed in future releases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3985 | * Use `V7_NULL` instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3986 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3987 | NOINSTR v7_val_t v7_mk_null(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3989 | /* Returns true if given value is a primitive `null` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3990 | int v7_is_null(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3991 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 3992 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 3993 | * Make `undefined` primitive value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3994 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 3995 | * NOTE: this function is deprecated and will be removed in future releases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3996 | * Use `V7_UNDEFINED` instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 3997 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 3998 | NOINSTR v7_val_t v7_mk_undefined(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 3999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4000 | /* Returns true if given value is a primitive `undefined` value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4001 | int v7_is_undefined(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4003 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4004 | * Make JavaScript value that holds C/C++ `void *` pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4005 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4006 | * A foreign value is completely opaque and JS code cannot do anything useful |
Marko Mikulicic |
0:c0ecb8bf28eb | 4007 | * with it except holding it in properties and passing it around. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4008 | * It behaves like a sealed object with no properties. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4009 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4010 | * NOTE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4011 | * Only valid pointers (as defined by each supported architecture) will fully |
Marko Mikulicic |
0:c0ecb8bf28eb | 4012 | * preserved. In particular, all supported 64-bit architectures (x86_64, ARM-64) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4013 | * actually define a 48-bit virtual address space. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4014 | * Foreign values will be sign-extended as required, i.e creating a foreign |
Marko Mikulicic |
0:c0ecb8bf28eb | 4015 | * value of something like `(void *) -1` will work as expected. This is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4016 | * important because in some 64-bit OSs (e.g. Solaris) the user stack grows |
Marko Mikulicic |
0:c0ecb8bf28eb | 4017 | * downwards from the end of the address space. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4018 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4019 | * If you need to store exactly sizeof(void*) bytes of raw data where |
Marko Mikulicic |
0:c0ecb8bf28eb | 4020 | * `sizeof(void*)` >= 8, please use byte arrays instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4021 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4022 | NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *ptr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4024 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4025 | * Returns `void *` pointer stored in `v7_val_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4026 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4027 | * Returns NULL if the value is not a foreign pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4028 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4029 | NOINSTR void *v7_get_ptr(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4031 | /* Returns true if given value holds `void *` pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4032 | int v7_is_foreign(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4033 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4034 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4035 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4036 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4038 | #endif /* CS_V7_SRC_PRIMITIVE_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4039 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4040 | #line 1 "v7/src/primitive.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4041 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4042 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4043 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4044 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4045 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4046 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4047 | #ifndef CS_V7_SRC_PRIMITIVE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4048 | #define CS_V7_SRC_PRIMITIVE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4050 | /* Amalgamated: #include "v7/src/primitive_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4052 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4054 | /* Returns true if given value is a number, not NaN and not Infinity. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4055 | V7_PRIVATE int is_finite(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4057 | V7_PRIVATE val_t pointer_to_value(void *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4058 | V7_PRIVATE void *get_ptr(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4060 | #endif /* CS_V7_SRC_PRIMITIVE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4061 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4062 | #line 1 "v7/src/string_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4063 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4064 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4065 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4066 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4067 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4069 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4070 | * === Strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 4071 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4073 | #ifndef CS_V7_SRC_STRING_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4074 | #define CS_V7_SRC_STRING_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4076 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4078 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4079 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4080 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4081 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4082 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4083 | * Creates a string primitive value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4084 | * `str` must point to the utf8 string of length `len`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4085 | * If `len` is ~0, `str` is assumed to be NUL-terminated and `strlen(str)` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4086 | * used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4087 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4088 | * If `copy` is non-zero, the string data is copied and owned by the GC. The |
Marko Mikulicic |
0:c0ecb8bf28eb | 4089 | * caller can free the string data afterwards. Otherwise (`copy` is zero), the |
Marko Mikulicic |
0:c0ecb8bf28eb | 4090 | * caller owns the string data, and is responsible for not freeing it while it |
Marko Mikulicic |
0:c0ecb8bf28eb | 4091 | * is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4092 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4093 | v7_val_t v7_mk_string(struct v7 *v7, const char *str, size_t len, int copy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4095 | /* Returns true if given value is a primitive string value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4096 | int v7_is_string(v7_val_t v); |
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 | * String length returned in `len`, which is allowed to be NULL. Returns NULL |
Marko Mikulicic |
0:c0ecb8bf28eb | 4102 | * if the value is not a string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4103 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4104 | * JS strings can contain embedded NUL chars and may or may not be NUL |
Marko Mikulicic |
0:c0ecb8bf28eb | 4105 | * terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4106 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4107 | * CAUTION: creating new JavaScript object, array, or string may kick in a |
Marko Mikulicic |
0:c0ecb8bf28eb | 4108 | * garbage collector, which in turn may relocate string data and invalidate |
Marko Mikulicic |
0:c0ecb8bf28eb | 4109 | * pointer returned by `v7_get_string()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4110 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4111 | * Short JS strings are embedded inside the `v7_val_t` value itself. This is why |
Marko Mikulicic |
0:c0ecb8bf28eb | 4112 | * a pointer to a `v7_val_t` is required. It also means that the string data |
Marko Mikulicic |
0:c0ecb8bf28eb | 4113 | * will become invalid once that `v7_val_t` value goes out of scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4114 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4115 | const char *v7_get_string(struct v7 *v7, v7_val_t *v, size_t *len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4116 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4117 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4118 | * Returns a pointer to the string stored in `v7_val_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4119 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4120 | * Returns NULL if the value is not a string or if the string is not compatible |
Marko Mikulicic |
0:c0ecb8bf28eb | 4121 | * with a C string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4122 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4123 | * C compatible strings contain exactly one NUL char, in terminal position. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4124 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4125 | * All strings owned by the V7 engine (see `v7_mk_string()`) are guaranteed to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4126 | * be NUL terminated. Out of these, those that don't include embedded NUL chars |
Marko Mikulicic |
0:c0ecb8bf28eb | 4127 | * are guaranteed to be C compatible. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4128 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4129 | const char *v7_get_cstring(struct v7 *v7, v7_val_t *v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4131 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4132 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4133 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4135 | #endif /* CS_V7_SRC_STRING_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4136 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4137 | #line 1 "v7/src/string.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4138 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4139 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4140 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4141 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4142 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4144 | #ifndef CS_V7_SRC_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4145 | #define CS_V7_SRC_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4147 | /* Amalgamated: #include "v7/src/string_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4148 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4149 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4151 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4152 | * Size of the extra space for strings mbuf that is needed to avoid frequent |
Marko Mikulicic |
0:c0ecb8bf28eb | 4153 | * reallocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 4154 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4155 | #define _V7_STRING_BUF_RESERVE 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 4156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4157 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4158 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4159 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4161 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4162 | V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, v7_val_t s, v7_val_t at, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4163 | double *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4164 | V7_PRIVATE int s_cmp(struct v7 *, val_t a, val_t b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4165 | V7_PRIVATE val_t s_concat(struct v7 *, val_t, val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4167 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4168 | * Convert a C string to to an unsigned integer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4169 | * `ok` will be set to true if the string conforms to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4170 | * an unsigned long. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4171 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4172 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4173 | V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4174 | unsigned long *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4175 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4176 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4177 | * Convert a V7 string to to an unsigned integer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4178 | * `ok` will be set to true if the string conforms to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4179 | * an unsigned long. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4180 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4181 | * Use it if only you need strong conformity of the value to an integer; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4182 | * otherwise, use `to_long()` or `to_number_v()` instead. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4183 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4184 | V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4186 | enum embstr_flags { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4187 | EMBSTR_ZERO_TERM = (1 << 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 4188 | EMBSTR_UNESCAPE = (1 << 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 4189 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4191 | V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4192 | size_t len, uint8_t /*enum embstr_flags*/ flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4194 | V7_PRIVATE size_t unescape(const char *s, size_t len, char *to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4195 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4196 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4197 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4198 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4199 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4200 | #endif /* CS_V7_SRC_STRING_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4201 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4202 | #line 1 "v7/src/exceptions_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4203 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4204 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4205 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4206 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4207 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4209 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4210 | * === Exceptions |
Marko Mikulicic |
0:c0ecb8bf28eb | 4211 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4213 | #ifndef CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4214 | #define CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4216 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4218 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4219 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4220 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4222 | /* Throw an exception with an already existing value. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4223 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4224 | enum v7_err v7_throw(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4226 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4227 | * Throw an exception with given formatted message. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4228 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4229 | * Pass "Error" as typ for a generic error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4230 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4231 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4232 | enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, ...); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4233 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4234 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4235 | * Rethrow the currently thrown object. In fact, it just returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 4236 | * V7_EXEC_EXCEPTION. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4237 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4238 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4239 | enum v7_err v7_rethrow(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4240 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4241 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4242 | * Returns the value that is being thrown at the moment, or `undefined` if |
Marko Mikulicic |
0:c0ecb8bf28eb | 4243 | * nothing is being thrown. If `is_thrown` is not `NULL`, it will be set |
Marko Mikulicic |
0:c0ecb8bf28eb | 4244 | * to either 0 or 1, depending on whether something is thrown at the moment. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4245 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4246 | v7_val_t v7_get_thrown_value(struct v7 *v7, unsigned char *is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4248 | /* Clears currently thrown value, if any. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4249 | void v7_clear_thrown_value(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4251 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4252 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4253 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4255 | #endif /* CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4256 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4257 | #line 1 "v7/src/exceptions.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4258 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4259 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4260 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4261 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4262 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4263 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4264 | #ifndef CS_V7_SRC_EXCEPTIONS_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4265 | #define CS_V7_SRC_EXCEPTIONS_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4267 | /* Amalgamated: #include "v7/src/exceptions_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4268 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4269 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4271 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4272 | * Try to perform some arbitrary call, and if the result is other than `V7_OK`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4273 | * "throws" an error with `V7_THROW()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4274 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4275 | #define V7_TRY2(call, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4276 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4277 | enum v7_err _e = call; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4278 | V7_CHECK2(_e == V7_OK, _e, clean_label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4279 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4280 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4281 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4282 | * Sets return value to the provided one, and `goto`s `clean`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4283 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4284 | * For this to work, you should have local `enum v7_err rcode` variable, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4285 | * and a `clean` label. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4286 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4287 | #define V7_THROW2(err_code, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4288 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4289 | (void) v7; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4290 | rcode = (err_code); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4291 | assert(rcode != V7_OK); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4292 | assert(!v7_is_undefined(v7->vals.thrown_error) && v7->is_thrown); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4293 | goto clean_label; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4294 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4296 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4297 | * Checks provided condition `cond`, and if it's false, then "throws" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4298 | * provided `err_code` (see `V7_THROW()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4299 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4300 | #define V7_CHECK2(cond, err_code, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4301 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4302 | if (!(cond)) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4303 | V7_THROW2(err_code, clean_label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4304 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4305 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4307 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4308 | * Checks provided condition `cond`, and if it's false, then "throws" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4309 | * internal error |
Marko Mikulicic |
0:c0ecb8bf28eb | 4310 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4311 | * TODO(dfrank): it would be good to have formatted string: then, we can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4312 | * specify file and line. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4313 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4314 | #define V7_CHECK_INTERNAL2(cond, clean_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4315 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4316 | if (!(cond)) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4317 | enum v7_err __rcode = v7_throwf(v7, "Error", "Internal error"); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4318 | (void) __rcode; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4319 | V7_THROW2(V7_INTERNAL_ERROR, clean_label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4320 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4321 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4322 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4323 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4324 | * Shortcuts for the macros above, but they assume the clean label `clean`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4325 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4327 | #define V7_TRY(call) V7_TRY2(call, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4328 | #define V7_THROW(err_code) V7_THROW2(err_code, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4329 | #define V7_CHECK(cond, err_code) V7_CHECK2(cond, err_code, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4330 | #define V7_CHECK_INTERNAL(cond) V7_CHECK_INTERNAL2(cond, clean) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4332 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4333 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4334 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4336 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4337 | * At the moment, most of the exception-related functions are public, and are |
Marko Mikulicic |
0:c0ecb8bf28eb | 4338 | * declared in `exceptions_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4339 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4341 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4342 | * Create an instance of the exception with type `typ` (see `TYPE_ERROR`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4343 | * `SYNTAX_ERROR`, etc), and message `msg`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4344 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4345 | V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4346 | const char *msg, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4347 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4348 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4349 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4350 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4352 | #endif /* CS_V7_SRC_EXCEPTIONS_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4353 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4354 | #line 1 "v7/src/object.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4355 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4356 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4357 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4358 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4359 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4361 | #ifndef CS_V7_SRC_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4362 | #define CS_V7_SRC_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4364 | /* Amalgamated: #include "v7/src/object_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4366 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4367 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4369 | V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4370 | V7_PRIVATE val_t v7_object_to_value(struct v7_object *o); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4371 | V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4373 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4374 | * Returns pointer to the struct representing an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4375 | * Given value must be an object (the caller can verify it |
Marko Mikulicic |
0:c0ecb8bf28eb | 4376 | * by calling `v7_is_object()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4377 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4378 | V7_PRIVATE struct v7_object *get_object_struct(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4380 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4381 | * Return true if given value is a JavaScript object (will return |
Marko Mikulicic |
0:c0ecb8bf28eb | 4382 | * false for function) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4383 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4384 | V7_PRIVATE int v7_is_generic_object(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4386 | V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4388 | V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4389 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4390 | size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4391 | v7_prop_attr_t attrs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4393 | V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4394 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4395 | size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4397 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4398 | * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated |
Marko Mikulicic |
0:c0ecb8bf28eb | 4399 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4400 | * Returns a pointer to the property structure, given an object and a name of |
Marko Mikulicic |
0:c0ecb8bf28eb | 4401 | * the property as a pointer to string buffer and length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4402 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4403 | * See also `v7_get_property_v` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4404 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4405 | V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4406 | const char *name, size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4408 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4409 | * Just like `v7_get_property`, but takes name as a `v7_val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4410 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4411 | V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4412 | v7_val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4413 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4415 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4416 | V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4417 | v7_val_t name, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4419 | V7_PRIVATE void v7_destroy_property(struct v7_property **p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4421 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4422 | V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4423 | val_t obj, val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4425 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4426 | * Like `set_property`, but takes property name as a `val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4427 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4428 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4429 | V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4430 | val_t val, struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4432 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4433 | * Like JavaScript assignment: set a property with given `name` + `len` at |
Marko Mikulicic |
0:c0ecb8bf28eb | 4434 | * the object `obj` to value `val`. Returns a property through the `res` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4435 | * (which may be `NULL` if return value is not required) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4436 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4437 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4438 | V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4439 | size_t len, v7_val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4440 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4442 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4443 | * Like `def_property()`, but takes property name as a `val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4444 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4445 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4446 | V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4447 | v7_prop_attr_desc_t attrs_desc, val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4448 | uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4449 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4451 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4452 | * Define object property, similar to JavaScript `Object.defineProperty()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4453 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4454 | * Just like public `v7_def()`, but returns `enum v7_err`, and therefore can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4455 | * throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4456 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4457 | * Additionally, takes param `as_assign`: if it is non-zero, it behaves |
Marko Mikulicic |
0:c0ecb8bf28eb | 4458 | * similarly to plain JavaScript assignment in terms of some exception-related |
Marko Mikulicic |
0:c0ecb8bf28eb | 4459 | * corner cases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4460 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4461 | * `res` may be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4462 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4463 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4464 | V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4465 | size_t len, v7_prop_attr_desc_t attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4466 | v7_val_t val, uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4467 | struct v7_property **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4469 | V7_PRIVATE int set_method(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4470 | v7_cfunction_t *func, int num_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4472 | V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4473 | v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4475 | /* Return address of property value or NULL if the passed property is NULL */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4476 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4477 | V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4478 | struct v7_property *p, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4480 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 4481 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4482 | * Additional context for property iteration of a proxied object, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 4483 | * `v7_next_prop()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4484 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4485 | struct prop_iter_proxy_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4486 | /* Proxy target object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4487 | v7_val_t target_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4488 | /* Proxy handler object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4489 | v7_val_t handler_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4491 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4492 | * array returned by the `ownKeys` callback, valid if only `has_own_keys` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4493 | * set |
Marko Mikulicic |
0:c0ecb8bf28eb | 4494 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4495 | v7_val_t own_keys; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4496 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4497 | * callback to get property descriptor, one of these: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4498 | * - a JS or cfunction `getOwnPropertyDescriptor` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4499 | * (if `has_get_own_prop_desc_C` is not set); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4500 | * - a C callback `v7_get_own_prop_desc_cb_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4501 | * (if `has_get_own_prop_desc_C` is set); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4502 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4503 | v7_val_t get_own_prop_desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4505 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4506 | * if `has_own_keys` is set, `own_key_idx` represents next index in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 4507 | * `own_keys` array |
Marko Mikulicic |
0:c0ecb8bf28eb | 4508 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4509 | unsigned own_key_idx : 29; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4511 | /* if set, `own_keys` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4512 | unsigned has_own_keys : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4513 | /* if set, `get_own_prop_desc` is valid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4514 | unsigned has_get_own_prop_desc : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4515 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4516 | * if set, `get_own_prop_desc` is a C callback `has_get_own_prop_desc_C`, not |
Marko Mikulicic |
0:c0ecb8bf28eb | 4517 | * a JS callback |
Marko Mikulicic |
0:c0ecb8bf28eb | 4518 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4519 | unsigned has_get_own_prop_desc_C : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4520 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4521 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4523 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4524 | * Like public function `v7_init_prop_iter_ctx()`, but it takes additional |
Marko Mikulicic |
0:c0ecb8bf28eb | 4525 | * argument `proxy_transp`; if it is zero, and the given `obj` is a Proxy, it |
Marko Mikulicic |
0:c0ecb8bf28eb | 4526 | * will iterate the properties of the proxy itself, not the Proxy's target. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4527 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4528 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4529 | V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4530 | int proxy_transp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4531 | struct prop_iter_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4532 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4533 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4534 | V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4535 | v7_val_t *name, v7_val_t *value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4536 | v7_prop_attr_t *attrs, int *ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4538 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4539 | * Set new prototype `proto` for the given object `obj`. Returns `0` at |
Marko Mikulicic |
0:c0ecb8bf28eb | 4540 | * success, `-1` at failure (it may fail if given `obj` is a function object: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4541 | * it's impossible to change function object's prototype) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4542 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4543 | V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4544 | struct v7_object *proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4546 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4547 | * Given a pointer to the object structure, returns a |
Marko Mikulicic |
0:c0ecb8bf28eb | 4548 | * pointer to the prototype object, or `NULL` if there is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4549 | * no prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4550 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4551 | V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4552 | struct v7_object *obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4553 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4554 | V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4556 | /* Get the property holding user data and destructor, or NULL */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4557 | V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4558 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4559 | #endif /* CS_V7_SRC_OBJECT_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4560 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4561 | #line 1 "v7/src/exec_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4562 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4563 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4564 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4565 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4566 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4567 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4568 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4569 | * === Execution of JavaScript code |
Marko Mikulicic |
0:c0ecb8bf28eb | 4570 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4572 | #ifndef CS_V7_SRC_EXEC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4573 | #define CS_V7_SRC_EXEC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4575 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4576 | |
Marko Mikulicic |
2:7762b98d31c7 | 4577 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 4578 | extern "C" { |
Marko Mikulicic |
2:7762b98d31c7 | 4579 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 4580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4581 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4582 | * Execute JavaScript `js_code`. The result of evaluation is stored in |
Marko Mikulicic |
0:c0ecb8bf28eb | 4583 | * the `result` variable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4584 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4585 | * Return: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4586 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4587 | * - V7_OK on success. `result` contains the result of execution. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4588 | * - V7_SYNTAX_ERROR if `js_code` in not a valid code. `result` is undefined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4589 | * - V7_EXEC_EXCEPTION if `js_code` threw an exception. `result` stores |
Marko Mikulicic |
0:c0ecb8bf28eb | 4590 | * an exception object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4591 | * - V7_AST_TOO_LARGE if `js_code` contains an AST segment longer than 16 bit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4592 | * `result` is undefined. To avoid this error, build V7 with V7_LARGE_AST. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4593 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4594 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4595 | enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4597 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4598 | * Options for `v7_exec_opt()`. To get default options, like `v7_exec()` uses, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4599 | * just zero out this struct. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4600 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4601 | struct v7_exec_opts { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4602 | /* Filename, used for stack traces only */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4603 | const char *filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4605 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4606 | * Object to be used as `this`. Note: when it is zeroed out, i.e. it's a |
Marko Mikulicic |
0:c0ecb8bf28eb | 4607 | * number `0`, the `undefined` value is assumed. It means that it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 4608 | * impossible to actually use the number `0` as `this` object, but it makes |
Marko Mikulicic |
0:c0ecb8bf28eb | 4609 | * little sense anyway. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4610 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4611 | v7_val_t this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4612 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4613 | /* Whether the given `js_code` should be interpreted as JSON, not JS code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4614 | unsigned is_json : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4615 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4616 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4617 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4618 | * Customizable version of `v7_exec()`: allows to specify various options, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 4619 | * `struct v7_exec_opts`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4620 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4621 | enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4622 | const struct v7_exec_opts *opts, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4624 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4625 | * Same as `v7_exec()`, but loads source code from `path` file. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4626 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4627 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4628 | enum v7_err v7_exec_file(struct v7 *v7, const char *path, v7_val_t *result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4630 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4631 | * Parse `str` and store corresponding JavaScript object in `res` variable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4632 | * String `str` should be '\0'-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4633 | * Return value and semantic is the same as for `v7_exec()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4634 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4635 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4636 | enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4638 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4639 | * Same as `v7_parse_json()`, but loads JSON string from `path`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4640 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4641 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4642 | enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4644 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4645 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4646 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4647 | * Compile JavaScript code `js_code` into the byte code and write generated |
Marko Mikulicic |
0:c0ecb8bf28eb | 4648 | * byte code into opened file stream `fp`. If `generate_binary_output` is 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4649 | * then generated byte code is in human-readable text format. Otherwise, it is |
Marko Mikulicic |
0:c0ecb8bf28eb | 4650 | * in the binary format, suitable for execution by V7 instance. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4651 | * NOTE: `fp` must be a valid, opened, writable file stream. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4652 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4653 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4654 | enum v7_err v7_compile(const char *js_code, int generate_binary_output, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4655 | int use_bcode, FILE *fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4656 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4657 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4659 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4660 | * Call function `func` with arguments `args`, using `this_obj` as `this`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4661 | * `args` should be an array containing arguments or `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4662 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4663 | * `res` can be `NULL` if return value is not required. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4664 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4665 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4666 | enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4667 | v7_val_t args, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4668 | |
Marko Mikulicic |
2:7762b98d31c7 | 4669 | #if defined(__cplusplus) |
Marko Mikulicic |
2:7762b98d31c7 | 4670 | } |
Marko Mikulicic |
2:7762b98d31c7 | 4671 | #endif /* __cplusplus */ |
Marko Mikulicic |
2:7762b98d31c7 | 4672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4673 | #endif /* CS_V7_SRC_EXEC_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4674 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4675 | #line 1 "v7/src/exec.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4676 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4677 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4678 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4679 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4680 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4682 | #ifndef CS_V7_SRC_EXEC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4683 | #define CS_V7_SRC_EXEC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4684 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4685 | /* Amalgamated: #include "v7/src/exec_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4687 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4689 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4690 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4691 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4692 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4693 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4694 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4695 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4696 | * At the moment, all exec-related functions are public, and are declared in |
Marko Mikulicic |
0:c0ecb8bf28eb | 4697 | * `exec_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4698 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4700 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4701 | enum v7_err _v7_compile(const char *js_code, size_t js_code_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4702 | int generate_binary_output, int use_bcode, FILE *fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4704 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4705 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4706 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4708 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4710 | #endif /* CS_V7_SRC_EXEC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4711 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4712 | #line 1 "v7/src/array_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4713 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4714 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4715 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4716 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4717 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4719 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4720 | * === Arrays |
Marko Mikulicic |
0:c0ecb8bf28eb | 4721 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4723 | #ifndef CS_V7_SRC_ARRAY_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4724 | #define CS_V7_SRC_ARRAY_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4725 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4726 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4727 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4728 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4729 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4730 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4732 | /* Make an empty array object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4733 | v7_val_t v7_mk_array(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4735 | /* Returns true if given value is an array object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4736 | int v7_is_array(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4737 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4738 | /* Returns length on an array. If `arr` is not an array, 0 is returned. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4739 | unsigned long v7_array_length(struct v7 *v7, v7_val_t arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4741 | /* Insert value `v` in array `arr` at the end of the array. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4742 | int v7_array_push(struct v7 *, v7_val_t arr, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4743 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4744 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4745 | * Like `v7_array_push()`, but "returns" value through the `res` pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4746 | * argument. `res` is allowed to be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4747 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4748 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 4749 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4750 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4751 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4752 | enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4753 | int *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4754 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4755 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4756 | * Return array member at index `index`. If `index` is out of bounds, undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 4757 | * is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4758 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4759 | v7_val_t v7_array_get(struct v7 *, v7_val_t arr, unsigned long index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4760 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4761 | /* Insert value `v` into `arr` at index `index`. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4762 | int v7_array_set(struct v7 *v7, v7_val_t arr, unsigned long index, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4764 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4765 | * Like `v7_array_set()`, but "returns" value through the `res` pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4766 | * argument. `res` is allowed to be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4767 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4768 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 4769 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4770 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4771 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4772 | enum v7_err v7_array_set_throwing(struct v7 *v7, v7_val_t arr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4773 | unsigned long index, v7_val_t v, int *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4775 | /* Delete value in array `arr` at index `index`, if it exists. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4776 | void v7_array_del(struct v7 *v7, v7_val_t arr, unsigned long index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4778 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4779 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4780 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4781 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4782 | #endif /* CS_V7_SRC_ARRAY_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4783 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4784 | #line 1 "v7/src/array.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4785 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4786 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4787 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4788 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4789 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4790 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4791 | #ifndef CS_V7_SRC_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4792 | #define CS_V7_SRC_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4794 | /* Amalgamated: #include "v7/src/array_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4796 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4798 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4799 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4800 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4802 | V7_PRIVATE v7_val_t v7_mk_dense_array(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4803 | V7_PRIVATE val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 4804 | v7_array_get2(struct v7 *v7, v7_val_t arr, unsigned long index, int *has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4805 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4806 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4807 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4808 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4810 | #endif /* CS_V7_SRC_ARRAY_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4811 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4812 | #line 1 "v7/src/conversion_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4813 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4814 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4815 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4816 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4817 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4818 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4819 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4820 | * === Conversion |
Marko Mikulicic |
0:c0ecb8bf28eb | 4821 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4823 | #ifndef CS_V7_SRC_CONVERSION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4824 | #define CS_V7_SRC_CONVERSION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4826 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4828 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4829 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4830 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4831 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4832 | /* Stringify mode, see `v7_stringify()` and `v7_stringify_throwing()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4833 | enum v7_stringify_mode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4834 | V7_STRINGIFY_DEFAULT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4835 | V7_STRINGIFY_JSON, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4836 | V7_STRINGIFY_DEBUG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4837 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4839 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4840 | * Generate string representation of the JavaScript value `val` into a buffer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4841 | * `buf`, `len`. If `len` is too small to hold a generated string, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4842 | * `v7_stringify()` allocates required memory. In that case, it is caller's |
Marko Mikulicic |
0:c0ecb8bf28eb | 4843 | * responsibility to free the allocated buffer. Generated string is guaranteed |
Marko Mikulicic |
0:c0ecb8bf28eb | 4844 | * to be 0-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4845 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4846 | * Available stringification modes are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4847 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4848 | * - `V7_STRINGIFY_DEFAULT`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4849 | * Convert JS value to string, using common JavaScript semantics: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4850 | * - If value is an object: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4851 | * - call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4852 | * - If `toString()` returned non-primitive value, call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4853 | * - If `valueOf()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4854 | * - Now we have a primitive, and if it's not a string, then stringify it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4855 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4856 | * - `V7_STRINGIFY_JSON`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4857 | * Generate JSON output |
Marko Mikulicic |
0:c0ecb8bf28eb | 4858 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4859 | * - `V7_STRINGIFY_DEBUG`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4860 | * Mostly like JSON, but will not omit non-JSON objects like functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4861 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4862 | * Example code: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4863 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4864 | * char buf[100], *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4865 | * p = v7_stringify(v7, obj, buf, sizeof(buf), V7_STRINGIFY_DEFAULT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4866 | * printf("JSON string: [%s]\n", p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4867 | * if (p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4868 | * free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4869 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4870 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4871 | char *v7_stringify(struct v7 *v7, v7_val_t v, char *buf, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4872 | enum v7_stringify_mode mode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4874 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4875 | * Like `v7_stringify()`, but "returns" value through the `res` pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 4876 | * argument. `res` must not be `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4877 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4878 | * Caller should check the error code returned, and if it's something other |
Marko Mikulicic |
0:c0ecb8bf28eb | 4879 | * than `V7_OK`, perform cleanup and return this code further. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4880 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4881 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 4882 | enum v7_err v7_stringify_throwing(struct v7 *v7, v7_val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4883 | size_t size, enum v7_stringify_mode mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 4884 | char **res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4886 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4887 | * A shortcut for `v7_stringify()` with `V7_STRINGIFY_JSON` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4888 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4889 | #define v7_to_json(a, b, c, d) v7_stringify(a, b, c, d, V7_STRINGIFY_JSON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4890 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4891 | /* Returns true if given value evaluates to true, as in `if (v)` statement. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4892 | int v7_is_truthy(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4894 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4895 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 4896 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4898 | #endif /* CS_V7_SRC_CONVERSION_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4899 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 4900 | #line 1 "v7/src/conversion.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 4901 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 4902 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4903 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 4904 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 4905 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4907 | #ifndef CS_V7_SRC_CONVERSION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4908 | #define CS_V7_SRC_CONVERSION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4910 | /* Amalgamated: #include "v7/src/conversion_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4912 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4913 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4914 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4915 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 4916 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4918 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4919 | * Conversion API |
Marko Mikulicic |
0:c0ecb8bf28eb | 4920 | * ============== |
Marko Mikulicic |
0:c0ecb8bf28eb | 4921 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4922 | * - If you need to convert any JS value to string using common JavaScript |
Marko Mikulicic |
0:c0ecb8bf28eb | 4923 | * semantics, use `to_string()`, which can convert to both `v7_val_t` or your |
Marko Mikulicic |
0:c0ecb8bf28eb | 4924 | * C buffer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4925 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4926 | * - If you need to convert any JS value to number using common JavaScript |
Marko Mikulicic |
0:c0ecb8bf28eb | 4927 | * semantics, use `to_number_v()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4928 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4929 | * - If you need to convert any JS value to primitive, without forcing it to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4930 | * string or number, use `to_primitive()` (see comments for this function for |
Marko Mikulicic |
0:c0ecb8bf28eb | 4931 | * details); |
Marko Mikulicic |
0:c0ecb8bf28eb | 4932 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4933 | * - If you have a primitive value, and you want to convert it to either string |
Marko Mikulicic |
0:c0ecb8bf28eb | 4934 | * or number, you can still use functions above: `to_string()` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 4935 | * `to_number_v()`. But if you want to save a bit of work, use: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4936 | * - `primitive_to_str()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4937 | * - `primitive_to_number()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4938 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4939 | * In fact, these are a bit lower level functions, which are used by |
Marko Mikulicic |
0:c0ecb8bf28eb | 4940 | * `to_string()` and `to_number_v()` after converting value to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4941 | * primitive. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4942 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4943 | * - If you want to call `valueOf()` on the object, use `obj_value_of()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4944 | * - If you want to call `toString()` on the object, use `obj_to_string()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4945 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4946 | * - If you need to convert any JS value to boolean using common JavaScript |
Marko Mikulicic |
0:c0ecb8bf28eb | 4947 | * semantics (as in the expression `if (v)` or `Boolean(v)`), use |
Marko Mikulicic |
0:c0ecb8bf28eb | 4948 | * `to_boolean_v()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4949 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4950 | * - If you want to get the JSON representation of a value, use |
Marko Mikulicic |
0:c0ecb8bf28eb | 4951 | * `to_json_or_debug()`, passing `0` as `is_debug` : writes data to your C |
Marko Mikulicic |
0:c0ecb8bf28eb | 4952 | * buffer; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4953 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4954 | * - There is one more kind of representation: `DEBUG`. It's very similar to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4955 | * JSON, but it will not omit non-JSON values, such as functions. Again, use |
Marko Mikulicic |
0:c0ecb8bf28eb | 4956 | * `to_json_or_debug()`, but pass `1` as `is_debug` this time: writes data to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4957 | * your C buffer; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4958 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4959 | * Additionally, for any kind of to-string conversion into C buffer, you can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4960 | * use a convenience wrapper function (mostly for public API), which can |
Marko Mikulicic |
0:c0ecb8bf28eb | 4961 | * allocate the buffer for you: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4962 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4963 | * - `v7_stringify_throwing()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4964 | * - `v7_stringify()` : the same as above, but doesn't throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4965 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4966 | * There are a couple of more specific conversions, which I'd like to probably |
Marko Mikulicic |
0:c0ecb8bf28eb | 4967 | * refactor or remove in the future: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4968 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4969 | * - `to_long()` : if given value is `undefined`, returns provided default |
Marko Mikulicic |
0:c0ecb8bf28eb | 4970 | * value; otherwise, converts value to number, and then truncates to `long`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4971 | * - `str_to_ulong()` : converts the value to string, and tries to parse it as |
Marko Mikulicic |
0:c0ecb8bf28eb | 4972 | * an integer. Use it if only you need strong conformity ov the value to an |
Marko Mikulicic |
0:c0ecb8bf28eb | 4973 | * integer (currently, it's used only when examining keys of array object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4974 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4975 | * ---------------------------------------------------------------------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 4976 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4977 | * TODO(dfrank): |
Marko Mikulicic |
0:c0ecb8bf28eb | 4978 | * - Rename functions like `v7_get_double(v7, )`, `get_object_struct()` to |
Marko Mikulicic |
0:c0ecb8bf28eb | 4979 | *something |
Marko Mikulicic |
0:c0ecb8bf28eb | 4980 | * that will clearly identify that they convert to some C entity, not |
Marko Mikulicic |
0:c0ecb8bf28eb | 4981 | * `v7_val_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4982 | * - Maybe make `to_string()` private? But then, there will be no way |
Marko Mikulicic |
0:c0ecb8bf28eb | 4983 | * in public API to convert value to `v7_val_t` string, so, for now |
Marko Mikulicic |
0:c0ecb8bf28eb | 4984 | * it's here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4985 | * - When we agree on what goes to public API, and what does not, write |
Marko Mikulicic |
0:c0ecb8bf28eb | 4986 | * similar conversion guide for public API (in `conversion_public.h`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 4987 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 4988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 4989 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 4990 | * Convert any JS value to number, using common JavaScript semantics: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4991 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 4992 | * - If value is an object: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4993 | * - call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4994 | * - If `valueOf()` returned non-primitive value, call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 4995 | * - If `toString()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 4996 | * - Now we have a primitive, and if it's not a number, then: |
Marko Mikulicic |
0:c0ecb8bf28eb | 4997 | * - If `undefined`, return `NaN` |
Marko Mikulicic |
0:c0ecb8bf28eb | 4998 | * - If `null`, return 0.0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 4999 | * - If boolean, return either 1 or 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5000 | * - If string, try to parse it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5001 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5002 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5003 | V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, v7_val_t v, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5005 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5006 | * Convert any JS value to string, using common JavaScript semantics, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5007 | * see `v7_stringify()` and `V7_STRINGIFY_DEFAULT`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5008 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5009 | * This function can return multiple things: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5010 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5011 | * - String as a `v7_val_t` (if `res` is not `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5012 | * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 5013 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5014 | * - Length of actual string, independently of `buf_size` (if `res_len` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 5015 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5016 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5017 | * The rationale of having multiple formats of returned value is the following: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5018 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5019 | * Initially, to-string conversion always returned `v7_val_t`. But it turned |
Marko Mikulicic |
0:c0ecb8bf28eb | 5020 | * out that there are situations where such an approach adds useless pressure |
Marko Mikulicic |
0:c0ecb8bf28eb | 5021 | * on GC: e.g. when converting `undefined` to string, and the caller actually |
Marko Mikulicic |
0:c0ecb8bf28eb | 5022 | * needs a C buffer, not a `v7_val_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5023 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5024 | * Always returning string through `buf`+`buf_size` is bad as well: if we |
Marko Mikulicic |
0:c0ecb8bf28eb | 5025 | * convert from object to string, and either `toString()` or `valueOf()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5026 | * returned string, then we'd have to get string data from it, write to buffer, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5027 | * and if caller actually need `v7_val_t`, then it will have to create new |
Marko Mikulicic |
0:c0ecb8bf28eb | 5028 | * instance of the same string: again, useless GC pressure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5029 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5030 | * So, we have to use the combined approach. This function will make minimal |
Marko Mikulicic |
0:c0ecb8bf28eb | 5031 | * work depending on give `res` and `buf`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5032 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5033 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5034 | V7_PRIVATE enum v7_err to_string(struct v7 *v7, v7_val_t v, v7_val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5035 | char *buf, size_t buf_size, size_t *res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5037 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5038 | * Convert value to primitive, if it's not already. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5039 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5040 | * For object-to-primitive conversion, each object in JavaScript has two |
Marko Mikulicic |
0:c0ecb8bf28eb | 5041 | * methods: `toString()` and `valueOf()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5042 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5043 | * When converting object to string, JavaScript does the following: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5044 | * - call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5045 | * - If `toString()` returned non-primitive value, call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5046 | * - If `valueOf()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5047 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5048 | * When converting object to number, JavaScript calls the same functions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5049 | * but in reverse: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5050 | * - call `valueOf()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5051 | * - If `valueOf()` returned non-primitive value, call `toString()`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5052 | * - If `toString()` returned non-primitive value, throw `TypeError`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5053 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5054 | * This function `to_primitive()` performs either type of conversion, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5055 | * depending on the `hint` argument (see `enum to_primitive_hint`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5056 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5057 | enum to_primitive_hint { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5058 | /* Call `valueOf()` first, then `toString()` if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5059 | V7_TO_PRIMITIVE_HINT_NUMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5061 | /* Call `toString()` first, then `valueOf()` if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5062 | V7_TO_PRIMITIVE_HINT_STRING, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5064 | /* STRING for Date, NUMBER for everything else */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5065 | V7_TO_PRIMITIVE_HINT_AUTO, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5066 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5067 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5068 | enum v7_err to_primitive(struct v7 *v7, v7_val_t v, enum to_primitive_hint hint, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5069 | v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5070 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5071 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5072 | * Convert primitive value to string, using common JavaScript semantics. If |
Marko Mikulicic |
0:c0ecb8bf28eb | 5073 | * you need to convert any value to string (either object or primitive), |
Marko Mikulicic |
0:c0ecb8bf28eb | 5074 | * see `to_string()` or `v7_stringify_throwing()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5075 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5076 | * This function can return multiple things: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5077 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5078 | * - String as a `v7_val_t` (if `res` is not `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5079 | * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 5080 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5081 | * - Length of actual string, independently of `buf_size` (if `res_len` is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 5082 | * `NULL`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5083 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5084 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5085 | V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5086 | char *buf, size_t buf_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5087 | size_t *res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5088 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5089 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5090 | * Convert primitive value to number, using common JavaScript semantics. If you |
Marko Mikulicic |
0:c0ecb8bf28eb | 5091 | * need to convert any value to number (either object or primitive), see |
Marko Mikulicic |
0:c0ecb8bf28eb | 5092 | * `to_number_v()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5093 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5094 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5095 | V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5097 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5098 | * Convert value to JSON or "debug" representation, depending on whether |
Marko Mikulicic |
0:c0ecb8bf28eb | 5099 | * `is_debug` is non-zero. The "debug" is the same as JSON, but non-JSON values |
Marko Mikulicic |
0:c0ecb8bf28eb | 5100 | * (functions, `undefined`, etc) will not be omitted. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5101 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5102 | * See also `v7_stringify()`, `v7_stringify_throwing()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5103 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5104 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5105 | V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5106 | size_t size, size_t *res_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5107 | uint8_t is_debug); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5109 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5110 | * Calls `valueOf()` on given object `v` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5111 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5112 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5113 | V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5115 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5116 | * Calls `toString()` on given object `v` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5117 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5118 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5119 | V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5121 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5122 | * If given value is `undefined`, returns `default_value`; otherwise, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5123 | * converts value to number, and then truncates to `long`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5124 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5125 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5126 | V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5127 | long *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5128 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5129 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5130 | * Converts value to boolean as in the expression `if (v)` or `Boolean(v)`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5131 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5132 | * NOTE: it can't throw (even if the given value is an object with `valueOf()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5133 | * that throws), so it returns `val_t` directly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5134 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5135 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5136 | V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5138 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5139 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5140 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5142 | #endif /* CS_V7_SRC_CONVERSION_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5143 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5144 | #line 1 "v7/src/varint.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5145 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5146 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5147 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5148 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5149 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5151 | #ifndef CS_V7_SRC_VARINT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5152 | #define CS_V7_SRC_VARINT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5154 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5156 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5157 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5158 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5160 | V7_PRIVATE int encode_varint(size_t len, unsigned char *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5161 | V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5162 | V7_PRIVATE int calc_llen(size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5164 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5165 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5166 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5167 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5168 | #endif /* CS_V7_SRC_VARINT_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5169 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5170 | #line 1 "common/cs_strtod.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5171 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5172 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5173 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5174 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5175 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5177 | #ifndef CS_COMMON_CS_STRTOD_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5178 | #define CS_COMMON_CS_STRTOD_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5180 | double cs_strtod(const char *str, char **endptr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5182 | #endif /* CS_COMMON_CS_STRTOD_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5183 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5184 | #line 1 "v7/src/ast.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5185 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5186 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5187 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5188 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5189 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5191 | #ifndef CS_V7_SRC_AST_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5192 | #define CS_V7_SRC_AST_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5194 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 5195 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5196 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5197 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5199 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5201 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5202 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5203 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5204 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5205 | #define BIN_AST_SIGNATURE "V\007ASTV10" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5207 | enum ast_tag { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5208 | AST_NOP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5209 | AST_SCRIPT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5210 | AST_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5211 | AST_VAR_DECL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5212 | AST_FUNC_DECL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5213 | AST_IF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5214 | AST_FUNC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5216 | AST_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5217 | AST_REM_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5218 | AST_MUL_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5219 | AST_DIV_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5220 | AST_XOR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5221 | AST_PLUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5222 | AST_MINUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5223 | AST_OR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5224 | AST_AND_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5225 | AST_LSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5226 | AST_RSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5227 | AST_URSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5229 | AST_NUM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5230 | AST_IDENT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5231 | AST_STRING, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5232 | AST_REGEX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5233 | AST_LABEL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5234 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5235 | AST_SEQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5236 | AST_WHILE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5237 | AST_DOWHILE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5238 | AST_FOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5239 | AST_FOR_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5240 | AST_COND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5242 | AST_DEBUGGER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5243 | AST_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5244 | AST_LABELED_BREAK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5245 | AST_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5246 | AST_LABELED_CONTINUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5247 | AST_RETURN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5248 | AST_VALUE_RETURN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5249 | AST_THROW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5251 | AST_TRY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5252 | AST_SWITCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5253 | AST_CASE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5254 | AST_DEFAULT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5255 | AST_WITH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5257 | AST_LOGICAL_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5258 | AST_LOGICAL_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5259 | AST_OR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5260 | AST_XOR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5261 | AST_AND, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5263 | AST_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5264 | AST_EQ_EQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5265 | AST_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5266 | AST_NE_NE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5268 | AST_LE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5269 | AST_LT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5270 | AST_GE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5271 | AST_GT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5272 | AST_IN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5273 | AST_INSTANCEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5275 | AST_LSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5276 | AST_RSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5277 | AST_URSHIFT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5278 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5279 | AST_ADD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5280 | AST_SUB, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5282 | AST_REM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5283 | AST_MUL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5284 | AST_DIV, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5286 | AST_POSITIVE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5287 | AST_NEGATIVE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5288 | AST_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5289 | AST_LOGICAL_NOT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5290 | AST_VOID, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5291 | AST_DELETE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5292 | AST_TYPEOF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5293 | AST_PREINC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5294 | AST_PREDEC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5296 | AST_POSTINC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5297 | AST_POSTDEC, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5299 | AST_MEMBER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5300 | AST_INDEX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5301 | AST_CALL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5303 | AST_NEW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5305 | AST_ARRAY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5306 | AST_OBJECT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5307 | AST_PROP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5308 | AST_GETTER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5309 | AST_SETTER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5311 | AST_THIS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5312 | AST_TRUE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5313 | AST_FALSE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5314 | AST_NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5315 | AST_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5317 | AST_USE_STRICT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5319 | AST_MAX_TAG |
Marko Mikulicic |
0:c0ecb8bf28eb | 5320 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5322 | struct ast { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5323 | struct mbuf mbuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5324 | int refcnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5325 | int has_overflow; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5326 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5328 | typedef unsigned long ast_off_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5330 | #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5331 | #define GCC_HAS_PRAGMA_DIAGNOSTIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 5332 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5334 | #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 5335 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5336 | * TODO(mkm): GCC complains that bitfields on char are not standard |
Marko Mikulicic |
0:c0ecb8bf28eb | 5337 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5338 | #pragma GCC diagnostic push |
Marko Mikulicic |
0:c0ecb8bf28eb | 5339 | #pragma GCC diagnostic ignored "-Wpedantic" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5340 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5341 | struct ast_node_def { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5342 | #ifndef V7_DISABLE_AST_TAG_NAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5343 | const char *name; /* tag name, for debugging and serialization */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5344 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5345 | unsigned char has_varint : 1; /* has a varint body */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5346 | unsigned char has_inlined : 1; /* inlined data whose size is in varint fld */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5347 | unsigned char num_skips : 3; /* number of skips */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5348 | unsigned char num_subtrees : 3; /* number of fixed subtrees */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5349 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5350 | extern const struct ast_node_def ast_node_defs[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5351 | #if V7_ENABLE_FOOTPRINT_REPORT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5352 | extern const size_t ast_node_defs_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5353 | extern const size_t ast_node_defs_count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5354 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5355 | #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC |
Marko Mikulicic |
0:c0ecb8bf28eb | 5356 | #pragma GCC diagnostic pop |
Marko Mikulicic |
0:c0ecb8bf28eb | 5357 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5358 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5359 | enum ast_which_skip { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5360 | AST_END_SKIP = 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5361 | AST_VAR_NEXT_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5362 | AST_SCRIPT_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5363 | AST_FOR_BODY_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5364 | AST_DO_WHILE_COND_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5365 | AST_END_IF_TRUE_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5366 | AST_TRY_CATCH_SKIP = 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5367 | AST_TRY_FINALLY_SKIP = 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5368 | AST_FUNC_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5369 | AST_FUNC_BODY_SKIP = 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5370 | AST_SWITCH_DEFAULT_SKIP = 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5371 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5373 | V7_PRIVATE void ast_init(struct ast *, size_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5374 | V7_PRIVATE void ast_optimize(struct ast *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5375 | V7_PRIVATE void ast_free(struct ast *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5377 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5378 | * Begins an AST node by inserting a tag to the AST at the given offset. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5379 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5380 | * It also allocates space for the fixed_size payload and the space for |
Marko Mikulicic |
0:c0ecb8bf28eb | 5381 | * the skips. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5382 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5383 | * The caller is responsible for appending children. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5384 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5385 | * Returns the offset of the node payload (one byte after the tag). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5386 | * This offset can be passed to `ast_set_skip`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5387 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5388 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5389 | ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5391 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5392 | * Modify tag which is already added to buffer. Keeps `AST_TAG_LINENO_PRESENT` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5393 | * flag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5394 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5395 | V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5396 | enum ast_tag tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5398 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 5399 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5400 | * Add line_no varint after all skips of the tag at the offset `tag_off`, and |
Marko Mikulicic |
0:c0ecb8bf28eb | 5401 | * marks the tag byte. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5402 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5403 | * Byte at the offset `tag_off` should be a valid tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5404 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5405 | V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5406 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5408 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5409 | * Patches a given skip slot for an already emitted node with the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5410 | * current write cursor position (e.g. AST length). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5411 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5412 | * This is intended to be invoked when a node with a variable number |
Marko Mikulicic |
0:c0ecb8bf28eb | 5413 | * of child subtrees is closed, or when the consumers need a shortcut |
Marko Mikulicic |
0:c0ecb8bf28eb | 5414 | * to the next sibling. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5415 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5416 | * Each node type has a different number and semantic for skips, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5417 | * all of them defined in the `ast_which_skip` enum. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5418 | * All nodes having a variable number of child subtrees must define |
Marko Mikulicic |
0:c0ecb8bf28eb | 5419 | * at least the `AST_END_SKIP` skip, which effectively skips a node |
Marko Mikulicic |
0:c0ecb8bf28eb | 5420 | * boundary. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5421 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5422 | * Every tree reader can assume this and safely skip unknown nodes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5423 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5424 | * `pos` should be an offset of the byte right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5425 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5426 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5427 | ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5429 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5430 | * Patches a given skip slot for an already emitted node with the value |
Marko Mikulicic |
0:c0ecb8bf28eb | 5431 | * (stored as delta relative to the `pos` node) of the `where` argument. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5432 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5433 | V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5434 | ast_off_t where, enum ast_which_skip skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5436 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5437 | * Returns the offset in AST to which the given `skip` points. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5438 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5439 | * `pos` should be an offset of the byte right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5440 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5441 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5442 | ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5443 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5444 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5445 | * Returns the tag from the offset `ppos`, and shifts `ppos` by 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5446 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5447 | V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5449 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5450 | * Moves the cursor to the tag's varint and inlined data (if there are any, see |
Marko Mikulicic |
0:c0ecb8bf28eb | 5451 | * `struct ast_node_def::has_varint` and `struct ast_node_def::has_inlined`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5452 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5453 | * Technically, it skips node's "skips" and line number data, if either is |
Marko Mikulicic |
0:c0ecb8bf28eb | 5454 | * present. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5455 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5456 | * Assumes a cursor (`ppos`) positioned right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5457 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5458 | V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5460 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5461 | * Moves the cursor to the tag's subtrees (if there are any, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5462 | * see `struct ast_node_def::num_subtrees`), or to the next node in case the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5463 | * current node has no subtrees. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5464 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5465 | * Technically, it skips node's "skips", line number data, and inlined data, if |
Marko Mikulicic |
0:c0ecb8bf28eb | 5466 | * either is present. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5467 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5468 | * Assumes a cursor (`ppos`) positioned right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5469 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5470 | V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5472 | /* Helper to add a node with inlined data. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5473 | V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5474 | enum ast_tag tag, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5475 | size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5477 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5478 | * Returns the line number encoded in the node, or `0` in case of none is |
Marko Mikulicic |
0:c0ecb8bf28eb | 5479 | * encoded. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5480 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5481 | * `pos` should be an offset of the byte right after a tag. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5482 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5483 | V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5484 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5485 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5486 | * `pos` should be an offset of the byte right after a tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 5487 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5488 | V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5490 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5491 | * Returns the `double` number inlined in the node |
Marko Mikulicic |
0:c0ecb8bf28eb | 5492 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5493 | V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5494 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5495 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5496 | * Skips the node and all its subnodes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5497 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5498 | * Cursor (`ppos`) should be at the tag byte |
Marko Mikulicic |
0:c0ecb8bf28eb | 5499 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5500 | V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5502 | V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5503 | int depth); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5505 | V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5507 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5508 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5509 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5511 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5513 | #endif /* CS_V7_SRC_AST_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5514 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5515 | #line 1 "v7/src/bcode.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5516 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5517 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5518 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5519 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5520 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5521 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5522 | #ifndef CS_V7_SRC_BCODE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5523 | #define CS_V7_SRC_BCODE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5525 | #define BIN_BCODE_SIGNATURE "V\007BCODE:" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5527 | #if !defined(V7_NAMES_CNT_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5528 | #define V7_NAMES_CNT_WIDTH 10 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5529 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5531 | #if !defined(V7_ARGS_CNT_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5532 | #define V7_ARGS_CNT_WIDTH 8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5533 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5535 | #define V7_NAMES_CNT_MAX ((1 << V7_NAMES_CNT_WIDTH) - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5536 | #define V7_ARGS_CNT_MAX ((1 << V7_ARGS_CNT_WIDTH) - 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5538 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5539 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5540 | /* Amalgamated: #include "v7/src/opcodes.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5541 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5542 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5543 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5544 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5546 | enum bcode_inline_lit_type_tag { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5547 | BCODE_INLINE_STRING_TYPE_TAG = 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5548 | BCODE_INLINE_NUMBER_TYPE_TAG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5549 | BCODE_INLINE_FUNC_TYPE_TAG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5550 | BCODE_INLINE_REGEXP_TYPE_TAG, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5552 | BCODE_MAX_INLINE_TYPE_TAG |
Marko Mikulicic |
0:c0ecb8bf28eb | 5553 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5555 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5556 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5557 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5558 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5559 | typedef uint32_t bcode_off_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5560 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5561 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5562 | * Each JS function will have one bcode structure |
Marko Mikulicic |
0:c0ecb8bf28eb | 5563 | * containing the instruction stream, a literal table, and function |
Marko Mikulicic |
0:c0ecb8bf28eb | 5564 | * metadata. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5565 | * Instructions contain references to literals (strings, constants, etc) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5566 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5567 | * The bcode struct can be shared between function instances |
Marko Mikulicic |
0:c0ecb8bf28eb | 5568 | * and keeps a reference count used to free it in the function destructor. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5569 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5570 | struct bcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5571 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5572 | * Names + instruction opcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5573 | * Names are null-terminates strings. For function's bcode, there are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5574 | * - function name (for anonymous function, the name is still present: an |
Marko Mikulicic |
0:c0ecb8bf28eb | 5575 | * empty string); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5576 | * - arg names (a number of args is determined by `args_cnt`, see below); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5577 | * - local names (a number or locals can be calculated: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5578 | * `(names_cnt - args_cnt - 1)`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5579 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5580 | * For script's bcode, there are just local names. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5581 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5582 | struct v7_vec ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5584 | /* Literal table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5585 | struct v7_vec lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5586 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5587 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5588 | /* Name of the file from which this bcode was generated (used for debug) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5589 | void *filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5590 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5592 | /* Reference count */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5593 | uint8_t refcnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5594 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5595 | /* Total number of null-terminated strings in the beginning of `ops` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5596 | unsigned int names_cnt : V7_NAMES_CNT_WIDTH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5597 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5598 | /* Number of args (should be <= `(names_cnt + 1)`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5599 | unsigned int args_cnt : V7_ARGS_CNT_WIDTH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5601 | unsigned int strict_mode : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5602 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5603 | * If true this structure lives on read only memory, either |
Marko Mikulicic |
0:c0ecb8bf28eb | 5604 | * mmapped or constant data section. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5605 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5606 | unsigned int frozen : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5607 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5608 | /* If set, `ops.buf` points to ROM, so we shouldn't free it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5609 | unsigned int ops_in_rom : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5610 | /* Set for deserialized bcode. Used for metrics only */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5611 | unsigned int deserialized : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5612 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5613 | /* Set when `ops` contains function name as the first `name` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5614 | unsigned int func_name_present : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5616 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5617 | /* If set, `filename` points to ROM, so we shouldn't free it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5618 | unsigned int filename_in_rom : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5619 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5620 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5621 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5622 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5623 | * Bcode builder context: it contains mutable mbufs for opcodes and literals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5624 | * whereas the bcode itself contains just vectors (`struct v7_vec`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5625 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5626 | struct bcode_builder { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5627 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5628 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5630 | struct mbuf ops; /* names + instruction opcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5631 | struct mbuf lit; /* literal table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5632 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5634 | V7_PRIVATE void bcode_builder_init(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5635 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5636 | struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5637 | V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5638 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5639 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5640 | * Note: `filename` must be either: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5641 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5642 | * - `NULL`. In this case, `filename_in_rom` is ignored. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5643 | * - A pointer to ROM (or to any other unmanaged memory). `filename_in_rom` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5644 | * must be set to 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5645 | * - A pointer returned by `shdata_create()`, i.e. a pointer to shared data. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5646 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5647 | * If you need to copy filename from another bcode, just pass NULL initially, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5648 | * and after bcode is initialized, call `bcode_copy_filename_from()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5649 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5650 | * To get later a proper null-terminated filename string from bcode, use |
Marko Mikulicic |
0:c0ecb8bf28eb | 5651 | * `bcode_get_filename()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5652 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5653 | V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5654 | void *filename, uint8_t filename_in_rom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5655 | V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5656 | V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5657 | V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5659 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5660 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5661 | * Return a pointer to null-terminated filename string |
Marko Mikulicic |
0:c0ecb8bf28eb | 5662 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5663 | V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5664 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5666 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5667 | * Copy filename from `src` to `dst`. If source filename is a pointer to ROM, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5668 | * then just the pointer is copied; otherwise, appropriate shdata pointer is |
Marko Mikulicic |
0:c0ecb8bf28eb | 5669 | * retained. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5670 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5671 | V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5673 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5674 | * Serialize a bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5675 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5676 | * All literals, including functions, are inlined into `ops` data; see |
Marko Mikulicic |
0:c0ecb8bf28eb | 5677 | * the serialization logic in `bcode_op_lit()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5678 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5679 | * The root bcode looks just like a regular function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5680 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5681 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5682 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5683 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5684 | /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5685 | FILE *f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5687 | V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5688 | const char *data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5690 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 5691 | V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *, struct bcode *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5692 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5694 | /* mode of literal storage: in literal table or inlined in `ops` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5695 | enum lit_mode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5696 | /* literal stored in table, index is in `lit_t::lit_idx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5697 | LIT_MODE__TABLE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5698 | /* literal should be inlined in `ops`, value is in `lit_t::inline_val` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5699 | LIT_MODE__INLINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5700 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5702 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5703 | * Result of the addition of literal value to bcode (see `bcode_add_lit()`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5704 | * There are two possible cases: |
Marko Mikulicic |
0:c0ecb8bf28eb | 5705 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5706 | * - Literal is added to the literal table. In this case, `mode == |
Marko Mikulicic |
0:c0ecb8bf28eb | 5707 | * LIT_MODE__TABLE`, and the index of the literal is stored in `lit_idx` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5708 | * - Literal is not added anywhere, and should be inlined into `ops`. In this |
Marko Mikulicic |
0:c0ecb8bf28eb | 5709 | * case, `mode == LIT_MODE__INLINED`, and the value to inline is stored in |
Marko Mikulicic |
0:c0ecb8bf28eb | 5710 | * `inline_val`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5711 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5712 | * It's `bcode_op_lit()` who handles both of these cases. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5713 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5714 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5715 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5716 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5717 | * index in literal table; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5718 | * NOTE: valid if only `mode == LIT_MODE__TABLE` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5719 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5720 | size_t lit_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5722 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5723 | * value to be inlined into `ops`; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5724 | * NOTE: valid if only `mode == LIT_MODE__INLINED` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5725 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5726 | v7_val_t inline_val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5727 | } v; /* anonymous unions are a c11 feature */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5729 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5730 | * mode of literal storage (see `enum lit_mode`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5731 | * NOTE: we need one more bit, because enum can be signed |
Marko Mikulicic |
0:c0ecb8bf28eb | 5732 | * on some compilers (e.g. msvc) and thus will get signextended |
Marko Mikulicic |
0:c0ecb8bf28eb | 5733 | * when moved to a `enum lit_mode` variable basically corrupting |
Marko Mikulicic |
0:c0ecb8bf28eb | 5734 | * the value. See https://github.com/cesanta/v7/issues/551 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5735 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5736 | enum lit_mode mode : 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5737 | } lit_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5739 | V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5741 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 5742 | V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5743 | int line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5744 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5746 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5747 | * Add a literal to the bcode literal table, or just decide that the literal |
Marko Mikulicic |
0:c0ecb8bf28eb | 5748 | * should be inlined into `ops`. See `lit_t` for details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5749 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5750 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5751 | lit_t bcode_add_lit(struct bcode_builder *bbuilder, v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5753 | /* disabled because of short lits */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5754 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 5755 | V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5756 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5758 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5759 | * Emit an opcode `op`, and handle the literal `lit` (see `bcode_add_lit()`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5760 | * `lit_t`). Depending on the literal storage mode (see `enum lit_mode`), this |
Marko Mikulicic |
0:c0ecb8bf28eb | 5761 | * function either emits literal table index or inlines the literal directly |
Marko Mikulicic |
0:c0ecb8bf28eb | 5762 | * into `ops.` |
Marko Mikulicic |
0:c0ecb8bf28eb | 5763 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5764 | V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5765 | lit_t lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5767 | /* Helper function, equivalent of `bcode_op_lit(bbuilder, OP_PUSH_LIT, lit)` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5768 | V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5770 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5771 | * Add name to bcode. If `idx` is null, a name is appended to the end of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5772 | * `bcode->ops.buf`. If `idx` is provided, it should point to the index at |
Marko Mikulicic |
0:c0ecb8bf28eb | 5773 | * which new name should be inserted; and it is updated by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5774 | * `bcode_add_name()` to point right after newly added name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5775 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5776 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5777 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5778 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5779 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 5780 | /*V7_PRIVATE*/ enum v7_err |
Marko Mikulicic |
0:c0ecb8bf28eb | 5781 | bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5782 | size_t *idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5784 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5785 | * Takes a pointer to the beginning of `ops` buffer and names count, returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 5786 | * a pointer where actual opcodes begin (i.e. skips names). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5787 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5788 | * It takes two distinct arguments instead of just `struct bcode` pointer, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5789 | * because during bcode building `ops` is stored in builder. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5790 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5791 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5792 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5793 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5794 | /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5796 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5797 | * Given a pointer to `ops` (which should be `bcode->ops` or a pointer returned |
Marko Mikulicic |
0:c0ecb8bf28eb | 5798 | * from previous invocation of `bcode_next_name()`), yields a name string via |
Marko Mikulicic |
0:c0ecb8bf28eb | 5799 | * arguments `pname`, `plen`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5800 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 5801 | * Returns a pointer that should be given to `bcode_next_name()` to get a next |
Marko Mikulicic |
0:c0ecb8bf28eb | 5802 | * string (Whether there is a next string should be determined via the |
Marko Mikulicic |
0:c0ecb8bf28eb | 5803 | * `names_cnt`; since if there are no more names, this function will return an |
Marko Mikulicic |
0:c0ecb8bf28eb | 5804 | * invalid non-null pointer as next name pointer) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5805 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5806 | V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5808 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5809 | * Like `bcode_next_name()`, but instead of yielding a C string, it yields a |
Marko Mikulicic |
0:c0ecb8bf28eb | 5810 | * `val_t` value (via `res`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 5811 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5812 | V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5813 | char *ops, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5815 | V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5817 | V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5818 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5819 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 5820 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5821 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5822 | /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5823 | uint8_t op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5824 | /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5825 | bcode_off_t label, bcode_off_t target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5827 | V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5828 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5829 | * Reads varint-encoded integer from the provided pointer, and adjusts |
Marko Mikulicic |
0:c0ecb8bf28eb | 5830 | * the pointer appropriately |
Marko Mikulicic |
0:c0ecb8bf28eb | 5831 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5832 | V7_PRIVATE size_t bcode_get_varint(char **ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5834 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5835 | * Decode a literal value from a string of opcodes and update the cursor to |
Marko Mikulicic |
0:c0ecb8bf28eb | 5836 | * point past it |
Marko Mikulicic |
0:c0ecb8bf28eb | 5837 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5838 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 5839 | v7_val_t bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5841 | #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5842 | V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5843 | char **ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5844 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5846 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5848 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5850 | #endif /* CS_V7_SRC_BCODE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5851 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5852 | #line 1 "v7/src/gc_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5853 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5854 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5855 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5856 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5857 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5859 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5860 | * === Garbage Collector |
Marko Mikulicic |
0:c0ecb8bf28eb | 5861 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5863 | #ifndef CS_V7_SRC_GC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5864 | #define CS_V7_SRC_GC_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5866 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5868 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5869 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5870 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5872 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 5873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5874 | /* Heap metric id, see `v7_heap_stat()` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5875 | enum v7_heap_stat_what { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5876 | V7_HEAP_STAT_HEAP_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5877 | V7_HEAP_STAT_HEAP_USED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5878 | V7_HEAP_STAT_STRING_HEAP_RESERVED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5879 | V7_HEAP_STAT_STRING_HEAP_USED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5880 | V7_HEAP_STAT_OBJ_HEAP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5881 | V7_HEAP_STAT_OBJ_HEAP_FREE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5882 | V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5883 | V7_HEAP_STAT_FUNC_HEAP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5884 | V7_HEAP_STAT_FUNC_HEAP_FREE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5885 | V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5886 | V7_HEAP_STAT_PROP_HEAP_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5887 | V7_HEAP_STAT_PROP_HEAP_FREE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5888 | V7_HEAP_STAT_PROP_HEAP_CELL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5889 | V7_HEAP_STAT_FUNC_AST_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5890 | V7_HEAP_STAT_BCODE_OPS_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5891 | V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5892 | V7_HEAP_STAT_BCODE_LIT_DESER_SIZE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5893 | V7_HEAP_STAT_FUNC_OWNED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5894 | V7_HEAP_STAT_FUNC_OWNED_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 5895 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5897 | /* Returns a given heap statistics */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5898 | int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5899 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5901 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5902 | * Perform garbage collection. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5903 | * Pass true to full in order to reclaim unused heap back to the OS. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5904 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5905 | void v7_gc(struct v7 *v7, int full); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5907 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5908 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 5909 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5911 | #endif /* CS_V7_SRC_GC_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5912 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 5913 | #line 1 "v7/src/gc.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 5914 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5915 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5916 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 5917 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 5918 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5920 | #ifndef CS_V7_SRC_GC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5921 | #define CS_V7_SRC_GC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5923 | /* Amalgamated: #include "v7/src/gc_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5925 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5926 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5928 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5929 | * Macros for marking reachable things: use bit 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5930 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5931 | #define MARK(p) (((struct gc_cell *) (p))->head.word |= 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5932 | #define UNMARK(p) (((struct gc_cell *) (p))->head.word &= ~1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5933 | #define MARKED(p) (((struct gc_cell *) (p))->head.word & 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5935 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5936 | * Similar to `MARK()` / `UNMARK()` / `MARKED()`, but `.._FREE` counterparts |
Marko Mikulicic |
0:c0ecb8bf28eb | 5937 | * are intended to mark free cells (as opposed to used ones), so they use |
Marko Mikulicic |
0:c0ecb8bf28eb | 5938 | * bit 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 5939 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5940 | #define MARK_FREE(p) (((struct gc_cell *) (p))->head.word |= 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5941 | #define UNMARK_FREE(p) (((struct gc_cell *) (p))->head.word &= ~2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5942 | #define MARKED_FREE(p) (((struct gc_cell *) (p))->head.word & 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5944 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 5945 | * performs arithmetics on gc_cell pointers as if they were arena->cell_size |
Marko Mikulicic |
0:c0ecb8bf28eb | 5946 | * bytes wide |
Marko Mikulicic |
0:c0ecb8bf28eb | 5947 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5948 | #define GC_CELL_OP(arena, cell, op, arg) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5949 | ((struct gc_cell *) (((char *) (cell)) op((arg) * (arena)->cell_size))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5950 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5951 | struct gc_tmp_frame { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5952 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5953 | size_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5954 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5956 | struct gc_cell { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5957 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5958 | struct gc_cell *link; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5959 | uintptr_t word; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5960 | } head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5961 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 5962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5963 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 5964 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 5965 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5967 | V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5968 | V7_PRIVATE struct v7_property *new_property(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5969 | V7_PRIVATE struct v7_js_function *new_function(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5971 | V7_PRIVATE void gc_mark(struct v7 *, val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5972 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5973 | V7_PRIVATE void gc_arena_init(struct gc_arena *, size_t, size_t, size_t, |
Marko Mikulicic |
0:c0ecb8bf28eb | 5974 | const char *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5975 | V7_PRIVATE void gc_arena_destroy(struct v7 *, struct gc_arena *a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5976 | V7_PRIVATE void gc_sweep(struct v7 *, struct gc_arena *, size_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5977 | V7_PRIVATE void *gc_alloc_cell(struct v7 *, struct gc_arena *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5979 | V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5980 | V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5981 | V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *, val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5983 | V7_PRIVATE void compute_need_gc(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5984 | /* perform gc if not inhibited */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5985 | V7_PRIVATE int maybe_gc(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5987 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5988 | V7_PRIVATE uint16_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 5989 | gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5990 | V7_PRIVATE int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5991 | V7_PRIVATE void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5992 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 5993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5994 | V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5996 | /* return 0 if v is an object/function with a bad pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 5997 | V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 5998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 5999 | /* checks whether a pointer is within the ranges of an arena */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6000 | V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6002 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 6003 | V7_PRIVATE size_t gc_arena_size(struct gc_arena *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6004 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6005 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6006 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6008 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6010 | #endif /* CS_V7_SRC_GC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6011 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6012 | #line 1 "v7/src/regexp_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6013 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6014 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6015 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6016 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6017 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6018 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6019 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6020 | * === RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 6021 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6022 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6023 | #ifndef CS_V7_SRC_REGEXP_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6024 | #define CS_V7_SRC_REGEXP_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6026 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6027 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6028 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6029 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6030 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6031 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6032 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6033 | * Make RegExp object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6034 | * `regex`, `regex_len` specify a pattern, `flags` and `flags_len` specify |
Marko Mikulicic |
0:c0ecb8bf28eb | 6035 | * flags. Both utf8 encoded. For example, `regex` is `(.+)`, `flags` is `gi`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6036 | * If `regex_len` is ~0, `regex` is assumed to be NUL-terminated and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6037 | * `strlen(regex)` is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6038 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6039 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6040 | enum v7_err v7_mk_regexp(struct v7 *v7, const char *regex, size_t regex_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6041 | const char *flags, size_t flags_len, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6042 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6043 | /* Returns true if given value is a JavaScript RegExp object*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6044 | int v7_is_regexp(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6046 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6047 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6048 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6050 | #endif /* CS_V7_SRC_REGEXP_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6051 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6052 | #line 1 "v7/src/regexp.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6053 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6054 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6055 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6056 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6057 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6059 | #ifndef CS_V7_SRC_REGEXP_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6060 | #define CS_V7_SRC_REGEXP_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6061 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6062 | /* Amalgamated: #include "v7/src/regexp_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6064 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6066 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 6067 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6068 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6069 | * Maximum number of flags returned by get_regexp_flags_str(). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6070 | * NOTE: does not include null-terminate byte. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6071 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6072 | #define _V7_REGEXP_MAX_FLAGS_LEN 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6073 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6074 | struct v7_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6076 | V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *, v7_val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6078 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6079 | * Generates a string containing regexp flags, e.g. "gi". |
Marko Mikulicic |
0:c0ecb8bf28eb | 6080 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6081 | * `buf` should point to a buffer of minimum `_V7_REGEXP_MAX_FLAGS_LEN` bytes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6082 | * Returns length of the resulted string (saved into `buf`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6083 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6084 | V7_PRIVATE size_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 6085 | get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6086 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6087 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6088 | #endif /* CS_V7_SRC_REGEXP_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6089 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6090 | #line 1 "v7/src/function_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6091 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6092 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6093 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6094 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6095 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6097 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6098 | * === Functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 6099 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6100 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6101 | #ifndef CS_V7_SRC_FUNCTION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6102 | #define CS_V7_SRC_FUNCTION_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6104 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6106 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6107 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6108 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6110 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6111 | * Make a JS function object backed by a cfunction. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6112 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6113 | * `func` is a C callback. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6114 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6115 | * A function object is JS object having the Function prototype that holds a |
Marko Mikulicic |
0:c0ecb8bf28eb | 6116 | * cfunction value in a hidden property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6117 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6118 | * The function object will have a `prototype` property holding an object that |
Marko Mikulicic |
0:c0ecb8bf28eb | 6119 | * will be used as the prototype of objects created when calling the function |
Marko Mikulicic |
0:c0ecb8bf28eb | 6120 | * with the `new` operator. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6121 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6122 | v7_val_t v7_mk_function(struct v7 *, v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6123 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6124 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6125 | * Make f a JS function with specified prototype `proto`, so that the resulting |
Marko Mikulicic |
0:c0ecb8bf28eb | 6126 | * function is better suited for the usage as a constructor. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6127 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6128 | v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6129 | v7_val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6131 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6132 | * Make a JS value that holds C/C++ callback pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6133 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6134 | * CAUTION: This is a low-level function value. It's not a real object and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6135 | * cannot hold user defined properties. You should use `v7_mk_function` unless |
Marko Mikulicic |
0:c0ecb8bf28eb | 6136 | * you know what you're doing. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6137 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6138 | v7_val_t v7_mk_cfunction(v7_cfunction_t *func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6140 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6141 | * Returns true if given value is callable (i.e. it's either a JS function or |
Marko Mikulicic |
0:c0ecb8bf28eb | 6142 | * cfunction) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6143 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6144 | int v7_is_callable(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6146 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6147 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6148 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6150 | #endif /* CS_V7_SRC_FUNCTION_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6151 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6152 | #line 1 "v7/src/function.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6153 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6154 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6155 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6156 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6157 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6159 | #ifndef CS_V7_SRC_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6160 | #define CS_V7_SRC_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6162 | /* Amalgamated: #include "v7/src/function_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6164 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6165 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6167 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6168 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6169 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6170 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6171 | V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6172 | V7_PRIVATE val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 6173 | mk_js_function(struct v7 *v7, struct v7_generic_object *scope, val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6174 | V7_PRIVATE int is_js_function(val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6175 | V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6177 | /* Returns true if given value holds a pointer to C callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6178 | V7_PRIVATE int is_cfunction_lite(v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6180 | /* Returns true if given value holds an object which represents C callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6181 | V7_PRIVATE int is_cfunction_obj(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6182 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6183 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6184 | * Returns `v7_cfunction_t *` callback pointer stored in `v7_val_t`, or NULL |
Marko Mikulicic |
0:c0ecb8bf28eb | 6185 | * if given value is neither cfunction pointer nor cfunction object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6186 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6187 | V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6189 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6190 | * Like v7_mk_function but also sets the function's `length` property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6191 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6192 | * The `length` property is useful for introspection and the stdlib defines it |
Marko Mikulicic |
0:c0ecb8bf28eb | 6193 | * for many core functions mostly because the ECMA test suite requires it and we |
Marko Mikulicic |
0:c0ecb8bf28eb | 6194 | * don't want to skip otherwise useful tests just because the `length` property |
Marko Mikulicic |
0:c0ecb8bf28eb | 6195 | * check fails early in the test. User defined functions don't need to specify |
Marko Mikulicic |
0:c0ecb8bf28eb | 6196 | * the length and passing -1 is a safe choice, as it will also reduce the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6197 | * footprint. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6198 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6199 | * The subtle difference between set `length` explicitly to 0 rather than |
Marko Mikulicic |
0:c0ecb8bf28eb | 6200 | * just defaulting the `0` value from the prototype is that in the former case |
Marko Mikulicic |
0:c0ecb8bf28eb | 6201 | * the property cannot be change since it's read only. This again, is important |
Marko Mikulicic |
0:c0ecb8bf28eb | 6202 | * only for ecma compliance and your user code might or might not find this |
Marko Mikulicic |
0:c0ecb8bf28eb | 6203 | * relevant. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6204 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6205 | * NODO(lsm): please don't combine v7_mk_function_arg and v7_mk_function |
Marko Mikulicic |
0:c0ecb8bf28eb | 6206 | * into one function. Currently `num_args` is useful only internally. External |
Marko Mikulicic |
0:c0ecb8bf28eb | 6207 | * users can just use `v7_def` to set the length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6208 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6209 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 6210 | v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *func, int num_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6212 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6213 | * Like v7_mk_function_with_proto but also sets the function's `length` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6214 | *property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6215 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6216 | * NODO(lsm): please don't combine mk_cfunction_obj_with_proto and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6217 | * v7_mk_function_with_proto. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6218 | * into one function. Currently `num_args` is useful only internally. External |
Marko Mikulicic |
0:c0ecb8bf28eb | 6219 | * users can just use `v7_def` to set the length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6220 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6221 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 6222 | v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7, v7_cfunction_t *f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6223 | int num_args, v7_val_t proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6224 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6225 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6226 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6227 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6229 | #endif /* CS_V7_SRC_FUNCTION_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6230 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6231 | #line 1 "v7/src/util_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6232 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6233 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6234 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6235 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6236 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6238 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6239 | * === Utility functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 6240 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6242 | #ifndef CS_V7_SRC_UTIL_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6243 | #define CS_V7_SRC_UTIL_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6244 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6245 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6246 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6247 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6248 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6249 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6251 | /* Output a string representation of the value to stdout. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6252 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6253 | void v7_print(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6255 | /* Output a string representation of the value to stdout followed by a newline. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6256 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6257 | void v7_println(struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6258 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6259 | /* Output a string representation of the value to a file. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6260 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6261 | void v7_fprint(FILE *f, struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6263 | /* Output a string representation of the value to a file followed by a newline. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6264 | * V7_STRINGIFY_DEBUG mode is used. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6265 | void v7_fprintln(FILE *f, struct v7 *v7, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6267 | /* Output stack trace recorded in the exception `e` to file `f` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6268 | void v7_fprint_stack_trace(FILE *f, struct v7 *v7, v7_val_t e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6270 | /* Output error object message and possibly stack trace to f */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6271 | void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, v7_val_t e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6272 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6273 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6275 | struct v7_property; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6277 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6278 | * C callback, analogue of JS callback `getOwnPropertyDescriptor()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6279 | * Callbacks of this type are used for C API only, see `m7_mk_proxy()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6280 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6281 | * `name` is the name of the property, and the function should fill `attrs` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 6282 | * `value` with the property data. Before this callback is called, `attrs` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 6283 | * set to 0, and `value` is `V7_UNDEFINED`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6284 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6285 | * It should return non-zero if the property should be considered existing, or |
Marko Mikulicic |
0:c0ecb8bf28eb | 6286 | * zero otherwise. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6287 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6288 | * You can inspect the property attributes with the `V7_PROP_ATTR_IS_*` macros. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6289 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6290 | typedef int(v7_get_own_prop_desc_cb_t)(struct v7 *v7, v7_val_t target, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6291 | v7_val_t name, v7_prop_attr_t *attrs, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6292 | v7_val_t *value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6293 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6294 | /* Handler for `v7_mk_proxy()`; each item is a cfunction */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6295 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6296 | v7_cfunction_t *get; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6297 | v7_cfunction_t *set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6298 | v7_cfunction_t *own_keys; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6299 | v7_get_own_prop_desc_cb_t *get_own_prop_desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6300 | } v7_proxy_hnd_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6302 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6303 | * Create a Proxy object, see: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6304 | * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6305 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6306 | * Only two traps are implemented so far: `get()` and `set()`. Note that |
Marko Mikulicic |
0:c0ecb8bf28eb | 6307 | * `Object.defineProperty()` bypasses the `set()` trap. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6308 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6309 | * If `target` is not an object, the empty object will be used, so it's safe |
Marko Mikulicic |
0:c0ecb8bf28eb | 6310 | * to pass `V7_UNDEFINED` as `target`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6311 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6312 | v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6313 | const v7_proxy_hnd_t *handler); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6315 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6317 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6318 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6319 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6321 | #endif /* CS_V7_SRC_UTIL_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6322 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6323 | #line 1 "v7/src/util.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6324 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6325 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6326 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6327 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6328 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6330 | #ifndef CS_V7_SRC_UTIL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6331 | #define CS_V7_SRC_UTIL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6333 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6334 | /* Amalgamated: #include "v7/src/util_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6336 | struct bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6338 | V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6340 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 6341 | V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6342 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6344 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6345 | * At the moment, all other utility functions are public, and are declared in |
Marko Mikulicic |
0:c0ecb8bf28eb | 6346 | * `util_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6347 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6348 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6349 | #endif /* CS_V7_SRC_UTIL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6350 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6351 | #line 1 "v7/src/shdata.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6352 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6353 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6354 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6355 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6356 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6358 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6359 | * shdata (stands for "shared data") is a simple module that allows to have |
Marko Mikulicic |
0:c0ecb8bf28eb | 6360 | * reference count for an arbitrary payload data, which will be freed as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6361 | * necessary. A poor man's shared_ptr. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6362 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6364 | #ifndef CS_V7_SRC_SHDATA_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6365 | #define CS_V7_SRC_SHDATA_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6366 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6367 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6369 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6370 | struct shdata { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6371 | /* Reference count */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6372 | uint8_t refcnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6374 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6375 | * Note: we'd use `unsigned char payload[];` here, but we can't, since this |
Marko Mikulicic |
0:c0ecb8bf28eb | 6376 | * feature was introduced in C99 only |
Marko Mikulicic |
0:c0ecb8bf28eb | 6377 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6378 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6380 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6381 | * Allocate memory chunk of appropriate size, copy given `payload` data there, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6382 | * retain (`shdata_retain()`), and return it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6383 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6384 | V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6386 | V7_PRIVATE struct shdata *shdata_create_from_string(const char *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6388 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6389 | * Increment reference count for the given shared data |
Marko Mikulicic |
0:c0ecb8bf28eb | 6390 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6391 | V7_PRIVATE void shdata_retain(struct shdata *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6393 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6394 | * Decrement reference count for the given shared data |
Marko Mikulicic |
0:c0ecb8bf28eb | 6395 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6396 | V7_PRIVATE void shdata_release(struct shdata *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6398 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6399 | * Get payload data |
Marko Mikulicic |
0:c0ecb8bf28eb | 6400 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6401 | V7_PRIVATE void *shdata_get_payload(struct shdata *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6402 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6403 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6404 | #endif /* CS_V7_SRC_SHDATA_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6405 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6406 | #line 1 "v7/src/eval.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6407 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6408 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6409 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6410 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6411 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6413 | #ifndef CS_V7_SRC_EVAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6414 | #define CS_V7_SRC_EVAL_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6415 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6416 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6417 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6419 | struct v7_call_frame_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6421 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6422 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6423 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6425 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6426 | V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6427 | val_t this_object, uint8_t reset_line_no, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6428 | val_t *_res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6430 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6431 | V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6432 | v7_val_t args, uint8_t is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6433 | v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6434 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6435 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6436 | V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6437 | const char *filename, val_t func, val_t args, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6438 | val_t this_object, int is_json, int fr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6439 | uint8_t is_constructor, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6441 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6442 | * Try to find the call frame whose `type_mask` intersects with the given |
Marko Mikulicic |
0:c0ecb8bf28eb | 6443 | * `type_mask`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6444 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6445 | * Start from the top call frame, and go deeper until the matching frame is |
Marko Mikulicic |
0:c0ecb8bf28eb | 6446 | * found, or there's no more call frames. If the needed frame was not found, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6447 | * returns `NULL`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6448 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6449 | V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6450 | uint8_t type_mask); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6451 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6452 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6453 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6454 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6456 | #endif /* CS_V7_SRC_EVAL_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6457 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6458 | #line 1 "v7/src/compiler.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6459 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6460 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6461 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6462 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6463 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6465 | #ifndef CS_V7_SRC_COMPILER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6466 | #define CS_V7_SRC_COMPILER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6467 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6468 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6469 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6470 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6472 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6474 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6475 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6476 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6478 | V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6479 | struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6481 | V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6482 | ast_off_t *ppos, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6484 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6485 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6486 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6488 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6490 | #endif /* CS_V7_SRC_COMPILER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6491 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6492 | #line 1 "v7/src/cyg_profile.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6493 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6494 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6495 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6496 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6497 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6499 | #ifndef CS_V7_SRC_CYG_PROFILE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6500 | #define CS_V7_SRC_CYG_PROFILE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6502 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6503 | * This file contains GCC/clang instrumentation callbacks, as well as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6504 | * accompanying code. The actual code in these callbacks depends on enabled |
Marko Mikulicic |
0:c0ecb8bf28eb | 6505 | * features. See cyg_profile.c for some implementation details rationale. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6506 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6508 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6510 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6512 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6513 | * Stack-tracking functionality: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6514 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6515 | * The idea is that the caller should allocate `struct stack_track_ctx` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6516 | * (typically on stack) in the function to track the stack usage of, and call |
Marko Mikulicic |
0:c0ecb8bf28eb | 6517 | * `v7_stack_track_start()` in the beginning. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6518 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6519 | * Before quitting current stack frame (for example, before returning from |
Marko Mikulicic |
0:c0ecb8bf28eb | 6520 | * function), call `v7_stack_track_end()`, which returns the maximum stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 6521 | * consumed size. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6522 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6523 | * These calls can be nested: for example, we may track the stack usage of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6524 | * whole application by using these functions in `main()`, as well as track |
Marko Mikulicic |
0:c0ecb8bf28eb | 6525 | * stack usage of any nested functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6526 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6527 | * Just to stress: both `v7_stack_track_start()` / `v7_stack_track_end()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6528 | * should be called for the same instance of `struct stack_track_ctx` in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6529 | * same stack frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6530 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6532 | /* stack tracking context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6533 | struct stack_track_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6534 | struct stack_track_ctx *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6535 | void *start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6536 | void *max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6537 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6538 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6539 | /* see explanation above */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6540 | void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6541 | /* see explanation above */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6542 | int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6544 | void v7_stack_stat_clean(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6546 | #endif /* V7_ENABLE_STACK_TRACKING */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6548 | #endif /* CS_V7_SRC_CYG_PROFILE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6549 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6550 | #line 1 "v7/builtin/builtin.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6551 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6552 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6553 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6554 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6555 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6557 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6558 | * === Non-Standard API |
Marko Mikulicic |
0:c0ecb8bf28eb | 6559 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6560 | * V7 has several non-standard extensions for `String.prototype` in |
Marko Mikulicic |
0:c0ecb8bf28eb | 6561 | * order to give a compact and fast API to access raw data obtained from |
Marko Mikulicic |
0:c0ecb8bf28eb | 6562 | * File, Socket, and hardware input/output such as I2C. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6563 | * V7 IO API functions return |
Marko Mikulicic |
0:c0ecb8bf28eb | 6564 | * string data as a result of read operations, and that string data is a |
Marko Mikulicic |
0:c0ecb8bf28eb | 6565 | * raw byte array. ECMA6 provides `ArrayBuffer` and `DataView` API for dealing |
Marko Mikulicic |
0:c0ecb8bf28eb | 6566 | * with raw bytes, because strings in JavaScript are Unicode. That standard |
Marko Mikulicic |
0:c0ecb8bf28eb | 6567 | * API is too bloated for the embedded use, and does not allow to use handy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6568 | * String API (e.g. `.match()`) against data. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6569 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6570 | * V7 internally stores strings as byte arrays. All strings created by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6571 | * String API are UTF8 encoded. Strings that are the result of |
Marko Mikulicic |
0:c0ecb8bf28eb | 6572 | * input/output API calls might not be a valid UTF8 strings, but nevertheless |
Marko Mikulicic |
0:c0ecb8bf28eb | 6573 | * they are represented as strings, and the following API allows to access |
Marko Mikulicic |
0:c0ecb8bf28eb | 6574 | * underlying byte sequence: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6575 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6576 | * ==== String.prototype.at(position) -> number or NaN |
Marko Mikulicic |
0:c0ecb8bf28eb | 6577 | * Return byte at index |
Marko Mikulicic |
0:c0ecb8bf28eb | 6578 | * `position`. Byte value is in 0,255 range. If `position` is out of bounds |
Marko Mikulicic |
0:c0ecb8bf28eb | 6579 | * (either negative or larger then the byte array length), NaN is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6580 | * Example: `"ы".at(0)` returns 0xd1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6581 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6582 | * ==== String.prototype.blen -> number |
Marko Mikulicic |
0:c0ecb8bf28eb | 6583 | * Return string length in bytes. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6584 | * Example: `"ы".blen` returns 2. Note that `"ы".length` is 1, since that |
Marko Mikulicic |
0:c0ecb8bf28eb | 6585 | * string consists of a single Unicode character (2-byte). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6586 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6587 | * === Builtin API |
Marko Mikulicic |
0:c0ecb8bf28eb | 6588 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6589 | * Builtin API provides additional JavaScript interfaces available for V7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6590 | * scripts. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6591 | * File API is a wrapper around standard C calls `fopen()`, `fclose()`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6592 | * `fread()`, `fwrite()`, `rename()`, `remove()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6593 | * Crypto API provides functions for base64, md5, and sha1 encoding/decoding. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6594 | * Socket API provides low-level socket API. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6595 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6596 | * ==== File.eval(file_name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6597 | * Parse and run `file_name`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6598 | * Throws an exception if the file doesn't exist, cannot be parsed or if the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6599 | * script throws any exception. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6600 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6601 | * ==== File.read(file_name) -> string or undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 6602 | * Read file `file_name` and return a string with a file content. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6603 | * On any error, return `undefined` as a result. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6604 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6605 | * ==== File.write(file_name, str) -> true or false |
Marko Mikulicic |
0:c0ecb8bf28eb | 6606 | * Write string `str` to a file `file_name`. Return `true` on success, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6607 | * `false` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6608 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6609 | * ==== File.open(file_name [, mode]) -> file_object or null |
Marko Mikulicic |
0:c0ecb8bf28eb | 6610 | * Open a file `path`. For |
Marko Mikulicic |
0:c0ecb8bf28eb | 6611 | * list of valid `mode` values, see `fopen()` documentation. If `mode` is |
Marko Mikulicic |
0:c0ecb8bf28eb | 6612 | * not specified, mode `rb` is used, i.e. file is opened in read-only mode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6613 | * Return an opened file object, or null on error. Example: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6614 | * `var f = File.open('/etc/passwd'); f.close();` |
Marko Mikulicic |
0:c0ecb8bf28eb | 6615 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6616 | * ==== file_obj.close() -> undefined |
Marko Mikulicic |
0:c0ecb8bf28eb | 6617 | * Close opened file object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6618 | * NOTE: it is user's responsibility to close all opened file streams. V7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6619 | * does not do that automatically. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6620 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6621 | * ==== file_obj.read() -> string |
Marko Mikulicic |
0:c0ecb8bf28eb | 6622 | * Read portion of data from |
Marko Mikulicic |
0:c0ecb8bf28eb | 6623 | * an opened file stream. Return string with data, or empty string on EOF |
Marko Mikulicic |
0:c0ecb8bf28eb | 6624 | * or error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6625 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6626 | * ==== file_obj.write(str) -> num_bytes_written |
Marko Mikulicic |
0:c0ecb8bf28eb | 6627 | * Write string `str` to the opened file object. Return number of bytes written. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6628 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6629 | * ==== File.rename(old_name, new_name) -> errno |
Marko Mikulicic |
0:c0ecb8bf28eb | 6630 | * Rename file `old_name` to |
Marko Mikulicic |
0:c0ecb8bf28eb | 6631 | * `new_name`. Return 0 on success, or `errno` value on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6632 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6633 | * ==== File.list(dir_name) -> array_of_names |
Marko Mikulicic |
0:c0ecb8bf28eb | 6634 | * Return a list of files in a given directory, or `undefined` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6635 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6636 | * ==== File.remove(file_name) -> errno |
Marko Mikulicic |
0:c0ecb8bf28eb | 6637 | * Delete file `file_name`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6638 | * Return 0 on success, or `errno` value on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6639 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6640 | * ==== Crypto.base64_encode(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6641 | * Base64-encode input string `str` and return encoded string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6642 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6643 | * ==== Crypto.base64_decode(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6644 | * Base64-decode input string `str` and return decoded string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6645 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6646 | * ==== Crypto.md5(str), Crypto.md5_hex(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6647 | * Generate MD5 hash from input string `str`. Return 16-byte hash (`md5()`), |
Marko Mikulicic |
0:c0ecb8bf28eb | 6648 | * or stringified hexadecimal representation of the hash (`md5_hex`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6649 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6650 | * ==== Crypto.sha1(str), Crypto.sha1_hex(str) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6651 | * Generate SHA1 hash from input string `str`. Return 20-byte hash (`sha1()`), |
Marko Mikulicic |
0:c0ecb8bf28eb | 6652 | * or stringified hexadecimal representation of the hash (`sha1_hex`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 6653 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6654 | * ==== Socket.connect(host, port [, is_udp]) -> socket_obj |
Marko Mikulicic |
0:c0ecb8bf28eb | 6655 | * Connect to a given host. `host` can be a string IP address, or a host name. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6656 | * Optional `is_udp` parameter, if true, indicates that socket should be UDP. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6657 | * Return socket object on success, null on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6658 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6659 | * ==== Socket.listen(port [, ip_address [,is_udp]]) -> socket_obj |
Marko Mikulicic |
0:c0ecb8bf28eb | 6660 | * Create a listening socket on a given port. Optional `ip_address` argument |
Marko Mikulicic |
0:c0ecb8bf28eb | 6661 | * specifies and IP address to bind to. Optional `is_udp` parameter, if true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6662 | * indicates that socket should be UDP. Return socket object on success, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6663 | * null on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6664 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6665 | * ==== socket_obj.accept() -> socket_obj |
Marko Mikulicic |
0:c0ecb8bf28eb | 6666 | * Sleep until new incoming connection is arrived. Return accepted socket |
Marko Mikulicic |
0:c0ecb8bf28eb | 6667 | * object on success, or `null` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6668 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6669 | * ==== socket_obj.close() -> numeric_errno |
Marko Mikulicic |
0:c0ecb8bf28eb | 6670 | * Close socket object. Return 0 on success, or system errno on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6671 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6672 | * ==== socket_obj.recv() -> string |
Marko Mikulicic |
0:c0ecb8bf28eb | 6673 | * Read data from socket. Return data string, or empty string if peer has |
Marko Mikulicic |
0:c0ecb8bf28eb | 6674 | * disconnected, or `null` on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6675 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6676 | * ==== socket_obj.recvAll() -> string |
Marko Mikulicic |
0:c0ecb8bf28eb | 6677 | * Same as `recv()`, but keeps reading data until socket is closed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6678 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6679 | * ==== sock.send(string) -> num_bytes_sent |
Marko Mikulicic |
0:c0ecb8bf28eb | 6680 | * Send string to the socket. Return number of bytes sent, or 0 on error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6681 | * Simple HTTP client example: |
Marko Mikulicic |
0:c0ecb8bf28eb | 6682 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6683 | * var s = Socket.connect("google.com", 80); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6684 | * s.send("GET / HTTP/1.0\n\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6685 | * var reply = s.recv(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6686 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6687 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6688 | #ifndef CS_V7_BUILTIN_BUILTIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6689 | #define CS_V7_BUILTIN_BUILTIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6690 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6691 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6693 | void init_file(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6694 | void init_socket(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6695 | void init_crypto(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6697 | #endif /* CS_V7_BUILTIN_BUILTIN_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6698 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6699 | #line 1 "v7/src/slre.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6700 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6701 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6702 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6703 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6704 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6705 | * This software is dual-licensed: you can redistribute it and/or modify |
Marko Mikulicic |
0:c0ecb8bf28eb | 6706 | * it under the terms of the GNU General Public License version 2 as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6707 | * published by the Free Software Foundation. For the terms of this |
Marko Mikulicic |
0:c0ecb8bf28eb | 6708 | * license, see <http://www.gnu.org/licenses/>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6709 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6710 | * You are free to use this software under the terms of the GNU General |
Marko Mikulicic |
0:c0ecb8bf28eb | 6711 | * Public License, but WITHOUT ANY WARRANTY; without even the implied |
Marko Mikulicic |
0:c0ecb8bf28eb | 6712 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6713 | * See the GNU General Public License for more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6714 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 6715 | * Alternatively, you can license this software under a commercial |
Marko Mikulicic |
0:c0ecb8bf28eb | 6716 | * license, as set out in <https://www.cesanta.com/license>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6717 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6719 | #ifndef CS_V7_SRC_SLRE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6720 | #define CS_V7_SRC_SLRE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6722 | /* Return codes for slre_compile() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6723 | enum slre_error { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6724 | SLRE_OK, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6725 | SLRE_INVALID_DEC_DIGIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6726 | SLRE_INVALID_HEX_DIGIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6727 | SLRE_INVALID_ESC_CHAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6728 | SLRE_UNTERM_ESC_SEQ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6729 | SLRE_SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6730 | SLRE_UNMATCH_LBR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6731 | SLRE_UNMATCH_RBR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6732 | SLRE_NUM_OVERFLOW, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6733 | SLRE_INF_LOOP_M_EMP_STR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6734 | SLRE_TOO_MANY_CHARSETS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6735 | SLRE_INV_CHARSET_RANGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6736 | SLRE_CHARSET_TOO_LARGE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6737 | SLRE_MALFORMED_CHARSET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6738 | SLRE_INVALID_BACK_REFERENCE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6739 | SLRE_TOO_MANY_CAPTURES, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6740 | SLRE_INVALID_QUANTIFIER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6741 | SLRE_BAD_CHAR_AFTER_USD |
Marko Mikulicic |
0:c0ecb8bf28eb | 6742 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6743 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6744 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 6745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6746 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 6747 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6748 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6749 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6750 | /* Regex flags */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6751 | #define SLRE_FLAG_G 1 /* Global - match in the whole string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6752 | #define SLRE_FLAG_I 2 /* Ignore case */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6753 | #define SLRE_FLAG_M 4 /* Multiline */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6754 | #define SLRE_FLAG_RE 8 /* flag RegExp/String */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6756 | /* Describes single capture */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6757 | struct slre_cap { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6758 | const char *start; /* points to the beginning of the capture group */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6759 | const char *end; /* points to the end of the capture group */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6760 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6761 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6762 | /* Describes all captures */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6763 | #define SLRE_MAX_CAPS 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 6764 | struct slre_loot { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6765 | int num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6766 | struct slre_cap caps[SLRE_MAX_CAPS]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6767 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6768 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6769 | /* Opaque structure that holds compiled regular expression */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6770 | struct slre_prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6771 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6772 | int slre_compile(const char *regexp, size_t regexp_len, const char *flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6773 | size_t flags_len, struct slre_prog **, int is_regex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6774 | int slre_exec(struct slre_prog *prog, int flag_g, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6775 | const char *end, struct slre_loot *loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6776 | void slre_free(struct slre_prog *prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6778 | int slre_match(const char *, size_t, const char *, size_t, const char *, size_t, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6779 | struct slre_loot *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6780 | int slre_replace(struct slre_loot *loot, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6781 | const char *replace, size_t rep_len, struct slre_loot *dst); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6782 | int slre_get_flags(struct slre_prog *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6784 | #ifdef __cplusplus |
Marko Mikulicic |
0:c0ecb8bf28eb | 6785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6786 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6787 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6788 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6789 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6790 | #endif /* CS_V7_SRC_SLRE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6791 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6792 | #line 1 "v7/src/stdlib.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6793 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6794 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6795 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6796 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6797 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6799 | #ifndef CS_V7_SRC_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6800 | #define CS_V7_SRC_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6802 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6803 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6804 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6805 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6806 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6807 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6809 | /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6811 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 6812 | V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 6813 | int is_json, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6815 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6816 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6817 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6818 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6819 | #endif /* CS_V7_SRC_STDLIB_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6820 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6821 | #line 1 "v7/src/heapusage.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6822 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6823 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6824 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6825 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6826 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6828 | #ifndef CS_V7_SRC_HEAPUSAGE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6829 | #define CS_V7_SRC_HEAPUSAGE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6831 | #if defined(V7_HEAPUSAGE_ENABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6832 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6833 | extern volatile int heap_dont_count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6835 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6836 | * Returns total heap-allocated size in bytes (without any overhead of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 6837 | * heap implementation) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6838 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6839 | size_t heapusage_alloc_size(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6841 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6842 | * Returns number of active allocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 6843 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6844 | size_t heapusage_allocs_cnt(void); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6846 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6847 | * Must be called before allocating some memory that should not be indicated as |
Marko Mikulicic |
0:c0ecb8bf28eb | 6848 | * memory consumed for some particular operation: for example, when we |
Marko Mikulicic |
0:c0ecb8bf28eb | 6849 | * preallocate some GC buffer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 6850 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6851 | #define heapusage_dont_count(a) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6852 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6853 | heap_dont_count = a; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6854 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6855 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6856 | #else /* V7_HEAPUSAGE_ENABLE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6857 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6858 | #define heapusage_alloc_size() (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6859 | #define heapusage_allocs_cnt() (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6860 | #define heapusage_dont_count(a) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6861 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6862 | #endif /* V7_HEAPUSAGE_ENABLE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6863 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6864 | #endif /* CS_V7_SRC_HEAPUSAGE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6865 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6866 | #line 1 "v7/src/std_proxy.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6867 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6868 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6869 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6870 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6871 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6873 | #ifndef CS_V7_SRC_STD_PROXY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6874 | #define CS_V7_SRC_STD_PROXY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6875 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6876 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6877 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6879 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6880 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6881 | #define _V7_PROXY_TARGET_NAME "__tgt" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6882 | #define _V7_PROXY_HANDLER_NAME "__hnd" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6884 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6885 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6886 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6888 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 6889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6890 | V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6892 | V7_PRIVATE void init_proxy(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6894 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6895 | * Returns whether the given name is one of the special Proxy names |
Marko Mikulicic |
0:c0ecb8bf28eb | 6896 | * (_V7_PROXY_TARGET_NAME or _V7_PROXY_HANDLER_NAME) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6897 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6898 | V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6899 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6900 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6901 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6902 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6903 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6904 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6906 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6907 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6908 | #endif /* CS_V7_SRC_STD_PROXY_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6909 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6910 | #line 1 "v7/src/freeze.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6911 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6912 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6913 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6914 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6915 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6917 | #ifndef CS_V7_SRC_FREEZE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6918 | #define CS_V7_SRC_FREEZE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6920 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 6921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6922 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6924 | struct v7_property; |
Marko Mikulicic |
0:c0ecb8bf28eb | 6925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6926 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6927 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6928 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6930 | V7_PRIVATE void freeze(struct v7 *v7, char *filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6931 | V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6932 | V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6934 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6935 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6936 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6937 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6938 | #endif /* V7_FREEZE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6940 | #endif /* CS_V7_SRC_FREEZE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6941 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6942 | #line 1 "v7/src/std_array.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6943 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6944 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6945 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6946 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6947 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6948 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6949 | #ifndef CS_V7_SRC_STD_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6950 | #define CS_V7_SRC_STD_ARRAY_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6952 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6954 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6955 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6956 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6957 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6958 | V7_PRIVATE void init_array(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6960 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6961 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6962 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6964 | #endif /* CS_V7_SRC_STD_ARRAY_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6965 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6966 | #line 1 "v7/src/std_boolean.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6967 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6968 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6969 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6970 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6971 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6972 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6973 | #ifndef CS_V7_SRC_STD_BOOLEAN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6974 | #define CS_V7_SRC_STD_BOOLEAN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6975 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6976 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6978 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6979 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 6980 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6982 | V7_PRIVATE void init_boolean(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 6983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6984 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 6985 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 6986 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6988 | #endif /* CS_V7_SRC_STD_BOOLEAN_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6989 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 6990 | #line 1 "v7/src/std_date.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 6991 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 6992 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 6993 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 6994 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 6995 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6996 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 6997 | #ifndef CS_V7_SRC_STD_DATE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6998 | #define CS_V7_SRC_STD_DATE_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 6999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7000 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7002 | #if V7_ENABLE__Date |
Marko Mikulicic |
0:c0ecb8bf28eb | 7003 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7004 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7005 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7006 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7007 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7008 | V7_PRIVATE void init_date(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7010 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7011 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7012 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7014 | #endif /* V7_ENABLE__Date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7015 | #endif /* CS_V7_SRC_STD_DATE_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7016 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7017 | #line 1 "v7/src/std_function.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7018 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7019 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7020 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7021 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7022 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7024 | #ifndef CS_V7_SRC_STD_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7025 | #define CS_V7_SRC_STD_FUNCTION_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7027 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7029 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7030 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7031 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7033 | V7_PRIVATE void init_function(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7035 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7036 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7037 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7039 | #endif /* CS_V7_SRC_STD_FUNCTION_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7040 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7041 | #line 1 "v7/src/std_json.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7042 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7043 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7044 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7045 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7046 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7047 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7048 | #ifndef CS_V7_SRC_STD_JSON_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7049 | #define CS_V7_SRC_STD_JSON_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7051 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7052 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7053 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7054 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7055 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7057 | V7_PRIVATE void init_json(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7059 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7061 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7063 | #endif /* CS_V7_SRC_STD_JSON_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7064 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7065 | #line 1 "v7/src/std_math.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7066 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7067 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7068 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7069 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7070 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7072 | #ifndef CS_V7_SRC_STD_MATH_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7073 | #define CS_V7_SRC_STD_MATH_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7074 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7075 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7076 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7077 | #if V7_ENABLE__Math |
Marko Mikulicic |
0:c0ecb8bf28eb | 7078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7079 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7080 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7081 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7083 | V7_PRIVATE void init_math(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7085 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7086 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7087 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7088 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7089 | #endif /* V7_ENABLE__Math */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7090 | #endif /* CS_V7_SRC_STD_MATH_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7091 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7092 | #line 1 "v7/src/std_number.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7093 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7094 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7095 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7096 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7097 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7098 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7099 | #ifndef CS_V7_SRC_STD_NUMBER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7100 | #define CS_V7_SRC_STD_NUMBER_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7102 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7104 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7105 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7106 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7107 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7108 | V7_PRIVATE void init_number(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7110 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7112 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7113 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7114 | #endif /* CS_V7_SRC_STD_NUMBER_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7115 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7116 | #line 1 "v7/src/std_object.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7117 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7118 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7119 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7120 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7121 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7123 | #ifndef CS_V7_SRC_STD_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7124 | #define CS_V7_SRC_STD_OBJECT_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7125 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7126 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7127 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7128 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7129 | struct v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7131 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7132 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7133 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7135 | V7_PRIVATE void init_object(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7136 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7137 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 7138 | V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7140 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7142 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7144 | #endif /* CS_V7_SRC_STD_OBJECT_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7145 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7146 | #line 1 "v7/src/std_regex.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7147 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7148 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7149 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7150 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7151 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7153 | #ifndef CS_V7_SRC_STD_REGEX_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7154 | #define CS_V7_SRC_STD_REGEX_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7156 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7157 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7159 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 7160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7161 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7162 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7163 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7164 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7165 | V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7166 | V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, v7_val_t rx, v7_val_t vstr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7167 | int lind, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7169 | V7_PRIVATE void init_regex(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7170 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7171 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7172 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7173 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7175 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7176 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7177 | #endif /* CS_V7_SRC_STD_REGEX_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7178 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7179 | #line 1 "v7/src/std_string.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7180 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7181 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7182 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7183 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7184 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7186 | #ifndef CS_V7_SRC_STD_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7187 | #define CS_V7_SRC_STD_STRING_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7189 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7190 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7192 | /* Max captures for String.replace() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7193 | #define V7_RE_MAX_REPL_SUB 20 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7195 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7196 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7197 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7199 | V7_PRIVATE void init_string(struct v7 *v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7201 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7202 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7203 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7204 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7205 | #endif /* CS_V7_SRC_STD_STRING_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7206 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7207 | #line 1 "v7/src/js_stdlib.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7208 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7209 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7210 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7211 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7212 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7214 | #ifndef CS_V7_SRC_JS_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7215 | #define CS_V7_SRC_JS_STDLIB_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7216 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7217 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7218 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7219 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7220 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7221 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7223 | V7_PRIVATE void init_js_stdlib(struct v7 *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7224 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7225 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7226 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7227 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7229 | #endif /* CS_V7_SRC_JS_STDLIB_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7230 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7231 | #line 1 "v7/src/main_public.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7232 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7233 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7234 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7235 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7236 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7238 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7239 | * === v7 main() |
Marko Mikulicic |
0:c0ecb8bf28eb | 7240 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7242 | #ifndef CS_V7_SRC_MAIN_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7243 | #define CS_V7_SRC_MAIN_PUBLIC_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7244 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7245 | /* Amalgamated: #include "v7/src/core_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7246 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7247 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7248 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7249 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7251 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7252 | * V7 executable main function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7253 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 7254 | * There are various callbacks available: |
Marko Mikulicic |
0:c0ecb8bf28eb | 7255 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 7256 | * `pre_freeze_init()` and `pre_init()` are optional intialization functions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7257 | * aimed to export any extra functionality into vanilla v7 engine. They are |
Marko Mikulicic |
0:c0ecb8bf28eb | 7258 | * called after v7 initialization, before executing given files or inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 7259 | * expressions. `pre_freeze_init()` is called before "freezing" v7 state; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7260 | * whereas `pre_init` called afterwards. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7261 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 7262 | * `post_init()`, if provided, is called after executing files and expressions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7263 | * before destroying v7 instance and exiting. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7264 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7265 | int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7266 | void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7268 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7270 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7272 | #endif /* CS_V7_SRC_MAIN_PUBLIC_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7273 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7274 | #line 1 "v7/src/main.h" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7275 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7276 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7277 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7278 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7279 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7280 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7281 | #ifndef CS_V7_SRC_MAIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7282 | #define CS_V7_SRC_MAIN_H_ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7284 | /* Amalgamated: #include "v7/src/main_public.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7286 | #endif /* CS_V7_SRC_MAIN_H_ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7287 | #ifndef V7_EXPORT_INTERNAL_HEADERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 7288 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7289 | #line 1 "common/mbuf.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7290 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7291 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7292 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7293 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7294 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7296 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 7297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7298 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7299 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7300 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7302 | #ifndef MBUF_REALLOC |
Marko Mikulicic |
0:c0ecb8bf28eb | 7303 | #define MBUF_REALLOC realloc |
Marko Mikulicic |
0:c0ecb8bf28eb | 7304 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7305 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7306 | #ifndef MBUF_FREE |
Marko Mikulicic |
0:c0ecb8bf28eb | 7307 | #define MBUF_FREE free |
Marko Mikulicic |
0:c0ecb8bf28eb | 7308 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7309 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7310 | void mbuf_init(struct mbuf *mbuf, size_t initial_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7311 | mbuf->len = mbuf->size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7312 | mbuf->buf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7313 | mbuf_resize(mbuf, initial_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7314 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7316 | void mbuf_free(struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7317 | if (mbuf->buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7318 | MBUF_FREE(mbuf->buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7319 | mbuf_init(mbuf, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7321 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7322 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7323 | void mbuf_resize(struct mbuf *a, size_t new_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7324 | if (new_size > a->size || (new_size < a->size && new_size >= a->len)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7325 | char *buf = (char *) MBUF_REALLOC(a->buf, new_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7326 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7327 | * In case realloc fails, there's not much we can do, except keep things as |
Marko Mikulicic |
0:c0ecb8bf28eb | 7328 | * they are. Note that NULL is a valid return value from realloc when |
Marko Mikulicic |
0:c0ecb8bf28eb | 7329 | * size == 0, but that is covered too. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7330 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7331 | if (buf == NULL && new_size != 0) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7332 | a->buf = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7333 | a->size = new_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7335 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7337 | void mbuf_trim(struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7338 | mbuf_resize(mbuf, mbuf->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7339 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7341 | size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7342 | char *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7344 | assert(a != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7345 | assert(a->len <= a->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7346 | assert(off <= a->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7347 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7348 | /* check overflow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7349 | if (~(size_t) 0 - (size_t) a->buf < len) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7351 | if (a->len + len <= a->size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7352 | memmove(a->buf + off + len, a->buf + off, a->len - off); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7353 | if (buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7354 | memcpy(a->buf + off, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7355 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7356 | a->len += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7357 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7358 | size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7359 | if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7360 | a->buf = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7361 | memmove(a->buf + off + len, a->buf + off, a->len - off); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7362 | if (buf != NULL) memcpy(a->buf + off, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7363 | a->len += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7364 | a->size = new_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7365 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7366 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7367 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7368 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7370 | return len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7371 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7373 | size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7374 | return mbuf_insert(a, a->len, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7375 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7377 | void mbuf_remove(struct mbuf *mb, size_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7378 | if (n > 0 && n <= mb->len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7379 | memmove(mb->buf, mb->buf + n, mb->len - n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7380 | mb->len -= n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7381 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7382 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7383 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7384 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7385 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7386 | #line 1 "common/str_util.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7387 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7388 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7389 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 7390 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 7391 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7393 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 7394 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7395 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7396 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7398 | size_t c_strnlen(const char *s, size_t maxlen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7399 | size_t l = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7400 | for (; l < maxlen && s[l] != '\0'; l++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7401 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7402 | return l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7403 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7405 | #define C_SNPRINTF_APPEND_CHAR(ch) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7406 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7407 | if (i < (int) buf_size) buf[i] = ch; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7408 | i++; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7409 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7411 | #define C_SNPRINTF_FLAG_ZERO 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7413 | #ifdef C_DISABLE_BUILTIN_SNPRINTF |
Marko Mikulicic |
0:c0ecb8bf28eb | 7414 | int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7415 | return vsnprintf(buf, buf_size, fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7417 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 7418 | static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7419 | int field_width) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7420 | char tmp[40]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7421 | int i = 0, k = 0, neg = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7422 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7423 | if (num < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7424 | neg++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7425 | num = -num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7428 | /* Print into temporary buffer - in reverse order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7429 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7430 | int rem = num % base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7431 | if (rem < 10) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7432 | tmp[k++] = '0' + rem; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7433 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7434 | tmp[k++] = 'a' + (rem - 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7435 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7436 | num /= base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7437 | } while (num > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7438 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7439 | /* Zero padding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7440 | if (flags && C_SNPRINTF_FLAG_ZERO) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7441 | while (k < field_width && k < (int) sizeof(tmp) - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7442 | tmp[k++] = '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7444 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7446 | /* And sign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7447 | if (neg) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7448 | tmp[k++] = '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7449 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7451 | /* Now output */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7452 | while (--k >= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7453 | C_SNPRINTF_APPEND_CHAR(tmp[k]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7454 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7456 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7457 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7459 | int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7460 | int ch, i = 0, len_mod, flags, precision, field_width; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7462 | while ((ch = *fmt++) != '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7463 | if (ch != '%') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7464 | C_SNPRINTF_APPEND_CHAR(ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7465 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7466 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7467 | * Conversion specification: |
Marko Mikulicic |
0:c0ecb8bf28eb | 7468 | * zero or more flags (one of: # 0 - <space> + ') |
Marko Mikulicic |
0:c0ecb8bf28eb | 7469 | * an optional minimum field width (digits) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7470 | * an optional precision (. followed by digits, or *) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7471 | * an optional length modifier (one of: hh h l ll L q j z t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7472 | * 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 | 7473 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7474 | flags = field_width = precision = len_mod = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7475 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7476 | /* Flags. only zero-pad flag is supported. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7477 | if (*fmt == '0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7478 | flags |= C_SNPRINTF_FLAG_ZERO; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7479 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7481 | /* Field width */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7482 | while (*fmt >= '0' && *fmt <= '9') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7483 | field_width *= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7484 | field_width += *fmt++ - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7485 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7486 | /* Dynamic field width */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7487 | if (*fmt == '*') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7488 | field_width = va_arg(ap, int); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7489 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7490 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7492 | /* Precision */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7493 | if (*fmt == '.') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7494 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7495 | if (*fmt == '*') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7496 | precision = va_arg(ap, int); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7497 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7498 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7499 | while (*fmt >= '0' && *fmt <= '9') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7500 | precision *= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7501 | precision += *fmt++ - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7502 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7503 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7504 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7506 | /* Length modifier */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7507 | switch (*fmt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7508 | case 'h': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7509 | case 'l': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7510 | case 'L': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7511 | case 'I': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7512 | case 'q': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7513 | case 'j': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7514 | case 'z': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7515 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 7516 | len_mod = *fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7517 | if (*fmt == 'h') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7518 | len_mod = 'H'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7519 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7520 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7521 | if (*fmt == 'l') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7522 | len_mod = 'q'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7523 | fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7525 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7526 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7528 | ch = *fmt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7529 | if (ch == 's') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7530 | const char *s = va_arg(ap, const char *); /* Always fetch parameter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7531 | int j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7532 | int pad = field_width - (precision >= 0 ? c_strnlen(s, precision) : 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7533 | for (j = 0; j < pad; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7534 | C_SNPRINTF_APPEND_CHAR(' '); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7535 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7537 | /* `s` may be NULL in case of %.*s */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7538 | if (s != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7539 | /* Ignore negative and 0 precisions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7540 | for (j = 0; (precision <= 0 || j < precision) && s[j] != '\0'; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7541 | C_SNPRINTF_APPEND_CHAR(s[j]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7544 | } else if (ch == 'c') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7545 | ch = va_arg(ap, int); /* Always fetch parameter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7546 | C_SNPRINTF_APPEND_CHAR(ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7547 | } else if (ch == 'd' && len_mod == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7548 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, int), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7549 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7550 | } else if (ch == 'd' && len_mod == 'l') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7551 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, long), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7552 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7553 | #ifdef SSIZE_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 7554 | } else if (ch == 'd' && len_mod == 'z') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7555 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, ssize_t), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7556 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7557 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7558 | } else if (ch == 'd' && len_mod == 'q') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7559 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, int64_t), 10, flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7560 | field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7561 | } else if ((ch == 'x' || ch == 'u') && len_mod == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7562 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7563 | ch == 'x' ? 16 : 10, flags, field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7564 | } else if ((ch == 'x' || ch == 'u') && len_mod == 'l') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7565 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned long), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7566 | ch == 'x' ? 16 : 10, flags, field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7567 | } else if ((ch == 'x' || ch == 'u') && len_mod == 'z') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7568 | i += c_itoa(buf + i, buf_size - i, va_arg(ap, size_t), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7569 | ch == 'x' ? 16 : 10, flags, field_width); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7570 | } else if (ch == 'p') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7571 | unsigned long num = (unsigned long) (uintptr_t) va_arg(ap, void *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7572 | C_SNPRINTF_APPEND_CHAR('0'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7573 | C_SNPRINTF_APPEND_CHAR('x'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7574 | i += c_itoa(buf + i, buf_size - i, num, 16, flags, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7575 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7576 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 7577 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7578 | * TODO(lsm): abort is not nice in a library, remove it |
Marko Mikulicic |
0:c0ecb8bf28eb | 7579 | * Also, ESP8266 SDK doesn't have it |
Marko Mikulicic |
0:c0ecb8bf28eb | 7580 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7581 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7582 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7583 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7584 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7585 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7586 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7587 | /* Zero-terminate the result */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7588 | if (buf_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7589 | buf[i < (int) buf_size ? i : (int) buf_size - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7590 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7592 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7593 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7594 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7595 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7596 | int c_snprintf(char *buf, size_t buf_size, const char *fmt, ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7597 | int result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7598 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7599 | va_start(ap, fmt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7600 | result = c_vsnprintf(buf, buf_size, fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7601 | va_end(ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7602 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7603 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7605 | #ifdef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7606 | int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7607 | int ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7608 | char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7610 | strncpy(buf, path, sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7611 | buf[sizeof(buf) - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7612 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7613 | /* Trim trailing slashes. Leave backslash for paths like "X:\" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7614 | p = buf + strlen(buf) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7615 | while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7616 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7617 | memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7618 | ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7620 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7621 | * Convert back to Unicode. If doubly-converted string does not match the |
Marko Mikulicic |
0:c0ecb8bf28eb | 7622 | * original, something is fishy, reject. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7623 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7624 | WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2), |
Marko Mikulicic |
0:c0ecb8bf28eb | 7625 | NULL, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7626 | if (strcmp(buf, buf2) != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7627 | wbuf[0] = L'\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7628 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7629 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7630 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7631 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7633 | #endif /* _WIN32 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7634 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7635 | /* The simplest O(mn) algorithm. Better implementation are GPLed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7636 | const char *c_strnstr(const char *s, const char *find, size_t slen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7637 | size_t find_length = strlen(find); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7638 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7640 | for (i = 0; i < slen; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7641 | if (i + find_length > slen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7642 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7643 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7645 | if (strncmp(&s[i], find, find_length) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7646 | return &s[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7647 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7648 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7649 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7650 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7651 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7652 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7653 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7654 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 7655 | #line 1 "common/utf.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 7656 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 7657 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7658 | * The authors of this software are Rob Pike and Ken Thompson. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7659 | * Copyright (c) 2002 by Lucent Technologies. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7660 | * Permission to use, copy, modify, and distribute this software for any |
Marko Mikulicic |
0:c0ecb8bf28eb | 7661 | * purpose without fee is hereby granted, provided that this entire notice |
Marko Mikulicic |
0:c0ecb8bf28eb | 7662 | * is included in all copies of any software which is or includes a copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 7663 | * or modification of this software and in all copies of the supporting |
Marko Mikulicic |
0:c0ecb8bf28eb | 7664 | * documentation for such software. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7665 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED |
Marko Mikulicic |
0:c0ecb8bf28eb | 7666 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE |
Marko Mikulicic |
0:c0ecb8bf28eb | 7667 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 7668 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7669 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7671 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 7672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7673 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7675 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7676 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7677 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7678 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7680 | #if CS_ENABLE_UTF8 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7681 | enum { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7682 | Bit1 = 7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7683 | Bitx = 6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7684 | Bit2 = 5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7685 | Bit3 = 4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7686 | Bit4 = 3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7687 | Bit5 = 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 7688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7689 | T1 = ((1 << (Bit1 + 1)) - 1) ^ 0xFF, /* 0000 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7690 | Tx = ((1 << (Bitx + 1)) - 1) ^ 0xFF, /* 1000 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7691 | T2 = ((1 << (Bit2 + 1)) - 1) ^ 0xFF, /* 1100 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7692 | T3 = ((1 << (Bit3 + 1)) - 1) ^ 0xFF, /* 1110 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7693 | T4 = ((1 << (Bit4 + 1)) - 1) ^ 0xFF, /* 1111 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7694 | T5 = ((1 << (Bit5 + 1)) - 1) ^ 0xFF, /* 1111 1000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7696 | Rune1 = (1 << (Bit1 + 0 * Bitx)) - 1, /* 0000 0000 0000 0000 0111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7697 | Rune2 = (1 << (Bit2 + 1 * Bitx)) - 1, /* 0000 0000 0000 0111 1111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7698 | Rune3 = (1 << (Bit3 + 2 * Bitx)) - 1, /* 0000 0000 1111 1111 1111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7699 | Rune4 = (1 << (Bit4 + 3 * Bitx)) - 1, /* 0011 1111 1111 1111 1111 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7701 | Maskx = (1 << Bitx) - 1, /* 0011 1111 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7702 | Testx = Maskx ^ 0xFF, /* 1100 0000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7704 | Bad = Runeerror |
Marko Mikulicic |
0:c0ecb8bf28eb | 7705 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7707 | int chartorune(Rune *rune, const char *str) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7708 | int c, c1, c2 /* , c3 */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7709 | unsigned short l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7711 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7712 | * one character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7713 | * 00000-0007F => T1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 7714 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7715 | c = *(uchar *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7716 | if (c < Tx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7717 | *rune = c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7718 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7719 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7721 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7722 | * two character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7723 | * 0080-07FF => T2 Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7724 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7725 | c1 = *(uchar *) (str + 1) ^ Tx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7726 | if (c1 & Testx) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7727 | if (c < T3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7728 | if (c < T2) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7729 | l = ((c << Bitx) | c1) & Rune2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7730 | if (l <= Rune1) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7731 | *rune = l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7732 | return 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7733 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7735 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7736 | * three character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7737 | * 0800-FFFF => T3 Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7738 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7739 | c2 = *(uchar *) (str + 2) ^ Tx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7740 | if (c2 & Testx) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7741 | if (c < T4) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7742 | l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7743 | if (l <= Rune2) goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7744 | *rune = l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7745 | return 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7746 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7748 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7749 | * four character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7750 | * 10000-10FFFF => T4 Tx Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7751 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7752 | /* if(UTFmax >= 4) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7753 | c3 = *(uchar*)(str+3) ^ Tx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7754 | if(c3 & Testx) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7755 | goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7756 | if(c < T5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7757 | l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & |
Marko Mikulicic |
0:c0ecb8bf28eb | 7758 | Rune4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7759 | if(l <= Rune3) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7760 | goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7761 | if(l > Runemax) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7762 | goto bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7763 | *rune = l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7764 | return 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7765 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7766 | } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7768 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7769 | * bad decoding |
Marko Mikulicic |
0:c0ecb8bf28eb | 7770 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7771 | bad: |
Marko Mikulicic |
0:c0ecb8bf28eb | 7772 | *rune = Bad; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7773 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7774 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7775 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7776 | int runetochar(char *str, Rune *rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7777 | unsigned short c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7779 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7780 | * one character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7781 | * 00000-0007F => 00-7F |
Marko Mikulicic |
0:c0ecb8bf28eb | 7782 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7783 | c = *rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7784 | if (c <= Rune1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7785 | str[0] = c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7786 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7789 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7790 | * two character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7791 | * 00080-007FF => T2 Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7792 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7793 | if (c <= Rune2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7794 | str[0] = T2 | (c >> 1 * Bitx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7795 | str[1] = Tx | (c & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7796 | return 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7797 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7799 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7800 | * three character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7801 | * 00800-0FFFF => T3 Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7802 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7803 | /* if(c > Runemax) |
Marko Mikulicic |
0:c0ecb8bf28eb | 7804 | c = Runeerror; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7805 | /* if(c <= Rune3) { */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7806 | str[0] = T3 | (c >> 2 * Bitx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7807 | str[1] = Tx | ((c >> 1 * Bitx) & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7808 | str[2] = Tx | (c & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7809 | return 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7810 | /* } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7812 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7813 | * four character sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 7814 | * 010000-1FFFFF => T4 Tx Tx Tx |
Marko Mikulicic |
0:c0ecb8bf28eb | 7815 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7816 | /* str[0] = T4 | (c >> 3*Bitx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7817 | str[1] = Tx | ((c >> 2*Bitx) & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7818 | str[2] = Tx | ((c >> 1*Bitx) & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7819 | str[3] = Tx | (c & Maskx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7820 | return 4; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7823 | int fullrune(const char *str, int n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7824 | int c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7826 | if (n <= 0) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7827 | c = *(uchar *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7828 | if (c < Tx) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7829 | if (c < T3) return n >= 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7830 | if (UTFmax == 3 || c < T4) return n >= 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7831 | return n >= 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7832 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7834 | int utfnlen(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 | const char *es; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7840 | es = s + m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7841 | for (n = 0; s < es; n++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7842 | c = *(uchar *) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7843 | if (c < Runeself) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7844 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7845 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7847 | if (!fullrune(s, es - s)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7848 | s += chartorune(&rune, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7849 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7850 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7851 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7853 | const char *utfnshift(const char *s, long m) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7854 | int c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7855 | long n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7856 | Rune rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7857 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7858 | for (n = 0; n < m; n++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7859 | c = *(uchar *) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7860 | if (c < Runeself) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7861 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7862 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7864 | s += chartorune(&rune, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 7865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7866 | return s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 7867 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 7868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7869 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7870 | * The authors of this software are Rob Pike and Ken Thompson. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7871 | * Copyright (c) 2002 by Lucent Technologies. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7872 | * Permission to use, copy, modify, and distribute this software for any |
Marko Mikulicic |
0:c0ecb8bf28eb | 7873 | * purpose without fee is hereby granted, provided that this entire notice |
Marko Mikulicic |
0:c0ecb8bf28eb | 7874 | * is included in all copies of any software which is or includes a copy |
Marko Mikulicic |
0:c0ecb8bf28eb | 7875 | * or modification of this software and in all copies of the supporting |
Marko Mikulicic |
0:c0ecb8bf28eb | 7876 | * documentation for such software. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7877 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED |
Marko Mikulicic |
0:c0ecb8bf28eb | 7878 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE |
Marko Mikulicic |
0:c0ecb8bf28eb | 7879 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 7880 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 7881 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7882 | #include <stdarg.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7883 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 7884 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 7886 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 7887 | * alpha ranges - |
Marko Mikulicic |
0:c0ecb8bf28eb | 7888 | * only covers ranges not in lower||upper |
Marko Mikulicic |
0:c0ecb8bf28eb | 7889 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7890 | static Rune __alpha2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 7891 | 0x00d8, 0x00f6, /* Ø - ö */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7892 | 0x00f8, 0x01f5, /* ø - ǵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7893 | 0x0250, 0x02a8, /* ɐ - ʨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7894 | 0x038e, 0x03a1, /* Ύ - Ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7895 | 0x03a3, 0x03ce, /* Σ - ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7896 | 0x03d0, 0x03d6, /* ϐ - ϖ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7897 | 0x03e2, 0x03f3, /* Ϣ - ϳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7898 | 0x0490, 0x04c4, /* Ґ - ӄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7899 | 0x0561, 0x0587, /* ա - և */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7900 | 0x05d0, 0x05ea, /* א - ת */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7901 | 0x05f0, 0x05f2, /* װ - ײ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7902 | 0x0621, 0x063a, /* ء - غ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7903 | 0x0640, 0x064a, /* ـ - ي */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7904 | 0x0671, 0x06b7, /* ٱ - ڷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7905 | 0x06ba, 0x06be, /* ں - ھ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7906 | 0x06c0, 0x06ce, /* ۀ - ێ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7907 | 0x06d0, 0x06d3, /* ې - ۓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7908 | 0x0905, 0x0939, /* अ - ह */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7909 | 0x0958, 0x0961, /* क़ - ॡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7910 | 0x0985, 0x098c, /* অ - ঌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7911 | 0x098f, 0x0990, /* এ - ঐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7912 | 0x0993, 0x09a8, /* ও - ন */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7913 | 0x09aa, 0x09b0, /* প - র */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7914 | 0x09b6, 0x09b9, /* শ - হ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7915 | 0x09dc, 0x09dd, /* ড় - ঢ় */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7916 | 0x09df, 0x09e1, /* য় - ৡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7917 | 0x09f0, 0x09f1, /* ৰ - ৱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7918 | 0x0a05, 0x0a0a, /* ਅ - ਊ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7919 | 0x0a0f, 0x0a10, /* ਏ - ਐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7920 | 0x0a13, 0x0a28, /* ਓ - ਨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7921 | 0x0a2a, 0x0a30, /* ਪ - ਰ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7922 | 0x0a32, 0x0a33, /* ਲ - ਲ਼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7923 | 0x0a35, 0x0a36, /* ਵ - ਸ਼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7924 | 0x0a38, 0x0a39, /* ਸ - ਹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7925 | 0x0a59, 0x0a5c, /* ਖ਼ - ੜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7926 | 0x0a85, 0x0a8b, /* અ - ઋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7927 | 0x0a8f, 0x0a91, /* એ - ઑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7928 | 0x0a93, 0x0aa8, /* ઓ - ન */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7929 | 0x0aaa, 0x0ab0, /* પ - ર */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7930 | 0x0ab2, 0x0ab3, /* લ - ળ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7931 | 0x0ab5, 0x0ab9, /* વ - હ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7932 | 0x0b05, 0x0b0c, /* ଅ - ଌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7933 | 0x0b0f, 0x0b10, /* ଏ - ଐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7934 | 0x0b13, 0x0b28, /* ଓ - ନ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7935 | 0x0b2a, 0x0b30, /* ପ - ର */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7936 | 0x0b32, 0x0b33, /* ଲ - ଳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7937 | 0x0b36, 0x0b39, /* ଶ - ହ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7938 | 0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7939 | 0x0b5f, 0x0b61, /* ୟ - ୡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7940 | 0x0b85, 0x0b8a, /* அ - ஊ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7941 | 0x0b8e, 0x0b90, /* எ - ஐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7942 | 0x0b92, 0x0b95, /* ஒ - க */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7943 | 0x0b99, 0x0b9a, /* ங - ச */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7944 | 0x0b9e, 0x0b9f, /* ஞ - ட */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7945 | 0x0ba3, 0x0ba4, /* ண - த */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7946 | 0x0ba8, 0x0baa, /* ந - ப */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7947 | 0x0bae, 0x0bb5, /* ம - வ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7948 | 0x0bb7, 0x0bb9, /* ஷ - ஹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7949 | 0x0c05, 0x0c0c, /* అ - ఌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7950 | 0x0c0e, 0x0c10, /* ఎ - ఐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7951 | 0x0c12, 0x0c28, /* ఒ - న */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7952 | 0x0c2a, 0x0c33, /* ప - ళ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7953 | 0x0c35, 0x0c39, /* వ - హ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7954 | 0x0c60, 0x0c61, /* ౠ - ౡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7955 | 0x0c85, 0x0c8c, /* ಅ - ಌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7956 | 0x0c8e, 0x0c90, /* ಎ - ಐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7957 | 0x0c92, 0x0ca8, /* ಒ - ನ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7958 | 0x0caa, 0x0cb3, /* ಪ - ಳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7959 | 0x0cb5, 0x0cb9, /* ವ - ಹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7960 | 0x0ce0, 0x0ce1, /* ೠ - ೡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7961 | 0x0d05, 0x0d0c, /* അ - ഌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7962 | 0x0d0e, 0x0d10, /* എ - ഐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7963 | 0x0d12, 0x0d28, /* ഒ - ന */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7964 | 0x0d2a, 0x0d39, /* പ - ഹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7965 | 0x0d60, 0x0d61, /* ൠ - ൡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7966 | 0x0e01, 0x0e30, /* ก - ะ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7967 | 0x0e32, 0x0e33, /* า - ำ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7968 | 0x0e40, 0x0e46, /* เ - ๆ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7969 | 0x0e5a, 0x0e5b, /* ๚ - ๛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7970 | 0x0e81, 0x0e82, /* ກ - ຂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7971 | 0x0e87, 0x0e88, /* ງ - ຈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7972 | 0x0e94, 0x0e97, /* ດ - ທ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7973 | 0x0e99, 0x0e9f, /* ນ - ຟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7974 | 0x0ea1, 0x0ea3, /* ມ - ຣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7975 | 0x0eaa, 0x0eab, /* ສ - ຫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7976 | 0x0ead, 0x0eae, /* ອ - ຮ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7977 | 0x0eb2, 0x0eb3, /* າ - ຳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7978 | 0x0ec0, 0x0ec4, /* ເ - ໄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7979 | 0x0edc, 0x0edd, /* ໜ - ໝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7980 | 0x0f18, 0x0f19, /* ༘ - ༙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7981 | 0x0f40, 0x0f47, /* ཀ - ཇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7982 | 0x0f49, 0x0f69, /* ཉ - ཀྵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7983 | 0x10d0, 0x10f6, /* ა - ჶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7984 | 0x1100, 0x1159, /* ᄀ - ᅙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7985 | 0x115f, 0x11a2, /* ᅟ - ᆢ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7986 | 0x11a8, 0x11f9, /* ᆨ - ᇹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7987 | 0x1e00, 0x1e9b, /* Ḁ - ẛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7988 | 0x1f50, 0x1f57, /* ὐ - ὗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7989 | 0x1f80, 0x1fb4, /* ᾀ - ᾴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7990 | 0x1fb6, 0x1fbc, /* ᾶ - ᾼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7991 | 0x1fc2, 0x1fc4, /* ῂ - ῄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7992 | 0x1fc6, 0x1fcc, /* ῆ - ῌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7993 | 0x1fd0, 0x1fd3, /* ῐ - ΐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7994 | 0x1fd6, 0x1fdb, /* ῖ - Ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7995 | 0x1fe0, 0x1fec, /* ῠ - Ῥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7996 | 0x1ff2, 0x1ff4, /* ῲ - ῴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7997 | 0x1ff6, 0x1ffc, /* ῶ - ῼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7998 | 0x210a, 0x2113, /* ℊ - ℓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 7999 | 0x2115, 0x211d, /* ℕ - ℝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8000 | 0x2120, 0x2122, /* ℠ - ™ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8001 | 0x212a, 0x2131, /* K - ℱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8002 | 0x2133, 0x2138, /* ℳ - ℸ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8003 | 0x3041, 0x3094, /* ぁ - ゔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8004 | 0x30a1, 0x30fa, /* ァ - ヺ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8005 | 0x3105, 0x312c, /* ㄅ - ㄬ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8006 | 0x3131, 0x318e, /* ㄱ - ㆎ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8007 | 0x3192, 0x319f, /* ㆒ - ㆟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8008 | 0x3260, 0x327b, /* ㉠ - ㉻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8009 | 0x328a, 0x32b0, /* ㊊ - ㊰ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8010 | 0x32d0, 0x32fe, /* ㋐ - ㋾ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8011 | 0x3300, 0x3357, /* ㌀ - ㍗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8012 | 0x3371, 0x3376, /* ㍱ - ㍶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8013 | 0x337b, 0x3394, /* ㍻ - ㎔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8014 | 0x3399, 0x339e, /* ㎙ - ㎞ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8015 | 0x33a9, 0x33ad, /* ㎩ - ㎭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8016 | 0x33b0, 0x33c1, /* ㎰ - ㏁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8017 | 0x33c3, 0x33c5, /* ㏃ - ㏅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8018 | 0x33c7, 0x33d7, /* ㏇ - ㏗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8019 | 0x33d9, 0x33dd, /* ㏙ - ㏝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8020 | 0x4e00, 0x9fff, /* 一 - 鿿 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8021 | 0xac00, 0xd7a3, /* 가 - 힣 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8022 | 0xf900, 0xfb06, /* 豈 - st */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8023 | 0xfb13, 0xfb17, /* ﬓ - ﬗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8024 | 0xfb1f, 0xfb28, /* ײַ - ﬨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8025 | 0xfb2a, 0xfb36, /* שׁ - זּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8026 | 0xfb38, 0xfb3c, /* טּ - לּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8027 | 0xfb40, 0xfb41, /* נּ - סּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8028 | 0xfb43, 0xfb44, /* ףּ - פּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8029 | 0xfb46, 0xfbb1, /* צּ - ﮱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8030 | 0xfbd3, 0xfd3d, /* ﯓ - ﴽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8031 | 0xfd50, 0xfd8f, /* ﵐ - ﶏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8032 | 0xfd92, 0xfdc7, /* ﶒ - ﷇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8033 | 0xfdf0, 0xfdf9, /* ﷰ - ﷹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8034 | 0xfe70, 0xfe72, /* ﹰ - ﹲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8035 | 0xfe76, 0xfefc, /* ﹶ - ﻼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8036 | 0xff66, 0xff6f, /* ヲ - ッ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8037 | 0xff71, 0xff9d, /* ア - ン */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8038 | 0xffa0, 0xffbe, /* ᅠ - ᄒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8039 | 0xffc2, 0xffc7, /* ᅡ - ᅦ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8040 | 0xffca, 0xffcf, /* ᅧ - ᅬ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8041 | 0xffd2, 0xffd7, /* ᅭ - ᅲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8042 | 0xffda, 0xffdc, /* ᅳ - ᅵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8043 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8045 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8046 | * alpha singlets - |
Marko Mikulicic |
0:c0ecb8bf28eb | 8047 | * only covers ranges not in lower||upper |
Marko Mikulicic |
0:c0ecb8bf28eb | 8048 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8049 | static Rune __alpha1[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8050 | 0x00aa, /* ª */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8051 | 0x00b5, /* µ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8052 | 0x00ba, /* º */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8053 | 0x03da, /* Ϛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8054 | 0x03dc, /* Ϝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8055 | 0x03de, /* Ϟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8056 | 0x03e0, /* Ϡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8057 | 0x06d5, /* ە */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8058 | 0x09b2, /* ল */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8059 | 0x0a5e, /* ਫ਼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8060 | 0x0a8d, /* ઍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8061 | 0x0ae0, /* ૠ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8062 | 0x0b9c, /* ஜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8063 | 0x0cde, /* ೞ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8064 | 0x0e4f, /* ๏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8065 | 0x0e84, /* ຄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8066 | 0x0e8a, /* ຊ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8067 | 0x0e8d, /* ຍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8068 | 0x0ea5, /* ລ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8069 | 0x0ea7, /* ວ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8070 | 0x0eb0, /* ະ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8071 | 0x0ebd, /* ຽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8072 | 0x1fbe, /* ι */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8073 | 0x207f, /* ⁿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8074 | 0x20a8, /* ₨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8075 | 0x2102, /* ℂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8076 | 0x2107, /* ℇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8077 | 0x2124, /* ℤ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8078 | 0x2126, /* Ω */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8079 | 0x2128, /* ℨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8080 | 0xfb3e, /* מּ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8081 | 0xfe74, /* ﹴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8082 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8084 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8085 | * space ranges |
Marko Mikulicic |
0:c0ecb8bf28eb | 8086 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8087 | static Rune __space2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8088 | 0x0009, 0x000a, /* tab and newline */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8089 | 0x0020, 0x0020, /* space */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8090 | 0x00a0, 0x00a0, /* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8091 | 0x2000, 0x200b, /* - */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8092 | 0x2028, 0x2029, /* - */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8093 | 0x3000, 0x3000, /* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8094 | 0xfeff, 0xfeff, /* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8095 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8097 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8098 | * lower case ranges |
Marko Mikulicic |
0:c0ecb8bf28eb | 8099 | * 3rd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8100 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8101 | static Rune __toupper2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8102 | 0x0061, 0x007a, 468, /* a-z A-Z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8103 | 0x00e0, 0x00f6, 468, /* à-ö À-Ö */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8104 | 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8105 | 0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8106 | 0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8107 | 0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8108 | 0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8109 | 0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8110 | 0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8111 | 0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8112 | 0x0430, 0x044f, 468, /* а-я А-Я */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8113 | 0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8114 | 0x045e, 0x045f, 420, /* ў-џ Ў-Џ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8115 | 0x0561, 0x0586, 452, /* ա-ֆ Ա-Ֆ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8116 | 0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8117 | 0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8118 | 0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8119 | 0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8120 | 0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8121 | 0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8122 | 0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8123 | 0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8124 | 0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8125 | 0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8126 | 0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8127 | 0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8128 | 0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8129 | 0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8130 | 0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8131 | 0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8132 | 0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8133 | 0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8134 | 0x2170, 0x217f, 484, /* ⅰ-ⅿ Ⅰ-Ⅿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8135 | 0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8136 | 0xff41, 0xff5a, 468, /* a-z A-Z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8137 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8139 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8140 | * lower case singlets |
Marko Mikulicic |
0:c0ecb8bf28eb | 8141 | * 2nd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8142 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8143 | static Rune __toupper1[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8144 | 0x00ff, 621, /* ÿ Ÿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8145 | 0x0101, 499, /* ā Ā */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8146 | 0x0103, 499, /* ă Ă */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8147 | 0x0105, 499, /* ą Ą */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8148 | 0x0107, 499, /* ć Ć */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8149 | 0x0109, 499, /* ĉ Ĉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8150 | 0x010b, 499, /* ċ Ċ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8151 | 0x010d, 499, /* č Č */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8152 | 0x010f, 499, /* ď Ď */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8153 | 0x0111, 499, /* đ Đ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8154 | 0x0113, 499, /* ē Ē */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8155 | 0x0115, 499, /* ĕ Ĕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8156 | 0x0117, 499, /* ė Ė */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8157 | 0x0119, 499, /* ę Ę */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8158 | 0x011b, 499, /* ě Ě */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8159 | 0x011d, 499, /* ĝ Ĝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8160 | 0x011f, 499, /* ğ Ğ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8161 | 0x0121, 499, /* ġ Ġ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8162 | 0x0123, 499, /* ģ Ģ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8163 | 0x0125, 499, /* ĥ Ĥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8164 | 0x0127, 499, /* ħ Ħ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8165 | 0x0129, 499, /* ĩ Ĩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8166 | 0x012b, 499, /* ī Ī */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8167 | 0x012d, 499, /* ĭ Ĭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8168 | 0x012f, 499, /* į Į */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8169 | 0x0131, 268, /* ı I */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8170 | 0x0133, 499, /* ij IJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8171 | 0x0135, 499, /* ĵ Ĵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8172 | 0x0137, 499, /* ķ Ķ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8173 | 0x013a, 499, /* ĺ Ĺ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8174 | 0x013c, 499, /* ļ Ļ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8175 | 0x013e, 499, /* ľ Ľ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8176 | 0x0140, 499, /* ŀ Ŀ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8177 | 0x0142, 499, /* ł Ł */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8178 | 0x0144, 499, /* ń Ń */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8179 | 0x0146, 499, /* ņ Ņ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8180 | 0x0148, 499, /* ň Ň */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8181 | 0x014b, 499, /* ŋ Ŋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8182 | 0x014d, 499, /* ō Ō */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8183 | 0x014f, 499, /* ŏ Ŏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8184 | 0x0151, 499, /* ő Ő */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8185 | 0x0153, 499, /* œ Œ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8186 | 0x0155, 499, /* ŕ Ŕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8187 | 0x0157, 499, /* ŗ Ŗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8188 | 0x0159, 499, /* ř Ř */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8189 | 0x015b, 499, /* ś Ś */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8190 | 0x015d, 499, /* ŝ Ŝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8191 | 0x015f, 499, /* ş Ş */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8192 | 0x0161, 499, /* š Š */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8193 | 0x0163, 499, /* ţ Ţ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8194 | 0x0165, 499, /* ť Ť */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8195 | 0x0167, 499, /* ŧ Ŧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8196 | 0x0169, 499, /* ũ Ũ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8197 | 0x016b, 499, /* ū Ū */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8198 | 0x016d, 499, /* ŭ Ŭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8199 | 0x016f, 499, /* ů Ů */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8200 | 0x0171, 499, /* ű Ű */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8201 | 0x0173, 499, /* ų Ų */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8202 | 0x0175, 499, /* ŵ Ŵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8203 | 0x0177, 499, /* ŷ Ŷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8204 | 0x017a, 499, /* ź Ź */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8205 | 0x017c, 499, /* ż Ż */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8206 | 0x017e, 499, /* ž Ž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8207 | 0x017f, 200, /* ſ S */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8208 | 0x0183, 499, /* ƃ Ƃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8209 | 0x0185, 499, /* ƅ Ƅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8210 | 0x0188, 499, /* ƈ Ƈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8211 | 0x018c, 499, /* ƌ Ƌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8212 | 0x0192, 499, /* ƒ Ƒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8213 | 0x0199, 499, /* ƙ Ƙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8214 | 0x01a1, 499, /* ơ Ơ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8215 | 0x01a3, 499, /* ƣ Ƣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8216 | 0x01a5, 499, /* ƥ Ƥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8217 | 0x01a8, 499, /* ƨ Ƨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8218 | 0x01ad, 499, /* ƭ Ƭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8219 | 0x01b0, 499, /* ư Ư */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8220 | 0x01b4, 499, /* ƴ Ƴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8221 | 0x01b6, 499, /* ƶ Ƶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8222 | 0x01b9, 499, /* ƹ Ƹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8223 | 0x01bd, 499, /* ƽ Ƽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8224 | 0x01c5, 499, /* Dž DŽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8225 | 0x01c6, 498, /* dž DŽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8226 | 0x01c8, 499, /* Lj LJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8227 | 0x01c9, 498, /* lj LJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8228 | 0x01cb, 499, /* Nj NJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8229 | 0x01cc, 498, /* nj NJ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8230 | 0x01ce, 499, /* ǎ Ǎ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8231 | 0x01d0, 499, /* ǐ Ǐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8232 | 0x01d2, 499, /* ǒ Ǒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8233 | 0x01d4, 499, /* ǔ Ǔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8234 | 0x01d6, 499, /* ǖ Ǖ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8235 | 0x01d8, 499, /* ǘ Ǘ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8236 | 0x01da, 499, /* ǚ Ǚ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8237 | 0x01dc, 499, /* ǜ Ǜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8238 | 0x01df, 499, /* ǟ Ǟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8239 | 0x01e1, 499, /* ǡ Ǡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8240 | 0x01e3, 499, /* ǣ Ǣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8241 | 0x01e5, 499, /* ǥ Ǥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8242 | 0x01e7, 499, /* ǧ Ǧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8243 | 0x01e9, 499, /* ǩ Ǩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8244 | 0x01eb, 499, /* ǫ Ǫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8245 | 0x01ed, 499, /* ǭ Ǭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8246 | 0x01ef, 499, /* ǯ Ǯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8247 | 0x01f2, 499, /* Dz DZ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8248 | 0x01f3, 498, /* dz DZ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8249 | 0x01f5, 499, /* ǵ Ǵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8250 | 0x01fb, 499, /* ǻ Ǻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8251 | 0x01fd, 499, /* ǽ Ǽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8252 | 0x01ff, 499, /* ǿ Ǿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8253 | 0x0201, 499, /* ȁ Ȁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8254 | 0x0203, 499, /* ȃ Ȃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8255 | 0x0205, 499, /* ȅ Ȅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8256 | 0x0207, 499, /* ȇ Ȇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8257 | 0x0209, 499, /* ȉ Ȉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8258 | 0x020b, 499, /* ȋ Ȋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8259 | 0x020d, 499, /* ȍ Ȍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8260 | 0x020f, 499, /* ȏ Ȏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8261 | 0x0211, 499, /* ȑ Ȑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8262 | 0x0213, 499, /* ȓ Ȓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8263 | 0x0215, 499, /* ȕ Ȕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8264 | 0x0217, 499, /* ȗ Ȗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8265 | 0x0253, 290, /* ɓ Ɓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8266 | 0x0254, 294, /* ɔ Ɔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8267 | 0x025b, 297, /* ɛ Ɛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8268 | 0x0260, 295, /* ɠ Ɠ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8269 | 0x0263, 293, /* ɣ Ɣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8270 | 0x0268, 291, /* ɨ Ɨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8271 | 0x0269, 289, /* ɩ Ɩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8272 | 0x026f, 289, /* ɯ Ɯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8273 | 0x0272, 287, /* ɲ Ɲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8274 | 0x0283, 282, /* ʃ Ʃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8275 | 0x0288, 282, /* ʈ Ʈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8276 | 0x0292, 281, /* ʒ Ʒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8277 | 0x03ac, 462, /* ά Ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8278 | 0x03cc, 436, /* ό Ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8279 | 0x03d0, 438, /* ϐ Β */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8280 | 0x03d1, 443, /* ϑ Θ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8281 | 0x03d5, 453, /* ϕ Φ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8282 | 0x03d6, 446, /* ϖ Π */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8283 | 0x03e3, 499, /* ϣ Ϣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8284 | 0x03e5, 499, /* ϥ Ϥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8285 | 0x03e7, 499, /* ϧ Ϧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8286 | 0x03e9, 499, /* ϩ Ϩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8287 | 0x03eb, 499, /* ϫ Ϫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8288 | 0x03ed, 499, /* ϭ Ϭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8289 | 0x03ef, 499, /* ϯ Ϯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8290 | 0x03f0, 414, /* ϰ Κ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8291 | 0x03f1, 420, /* ϱ Ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8292 | 0x0461, 499, /* ѡ Ѡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8293 | 0x0463, 499, /* ѣ Ѣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8294 | 0x0465, 499, /* ѥ Ѥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8295 | 0x0467, 499, /* ѧ Ѧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8296 | 0x0469, 499, /* ѩ Ѩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8297 | 0x046b, 499, /* ѫ Ѫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8298 | 0x046d, 499, /* ѭ Ѭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8299 | 0x046f, 499, /* ѯ Ѯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8300 | 0x0471, 499, /* ѱ Ѱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8301 | 0x0473, 499, /* ѳ Ѳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8302 | 0x0475, 499, /* ѵ Ѵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8303 | 0x0477, 499, /* ѷ Ѷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8304 | 0x0479, 499, /* ѹ Ѹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8305 | 0x047b, 499, /* ѻ Ѻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8306 | 0x047d, 499, /* ѽ Ѽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8307 | 0x047f, 499, /* ѿ Ѿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8308 | 0x0481, 499, /* ҁ Ҁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8309 | 0x0491, 499, /* ґ Ґ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8310 | 0x0493, 499, /* ғ Ғ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8311 | 0x0495, 499, /* ҕ Ҕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8312 | 0x0497, 499, /* җ Җ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8313 | 0x0499, 499, /* ҙ Ҙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8314 | 0x049b, 499, /* қ Қ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8315 | 0x049d, 499, /* ҝ Ҝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8316 | 0x049f, 499, /* ҟ Ҟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8317 | 0x04a1, 499, /* ҡ Ҡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8318 | 0x04a3, 499, /* ң Ң */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8319 | 0x04a5, 499, /* ҥ Ҥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8320 | 0x04a7, 499, /* ҧ Ҧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8321 | 0x04a9, 499, /* ҩ Ҩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8322 | 0x04ab, 499, /* ҫ Ҫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8323 | 0x04ad, 499, /* ҭ Ҭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8324 | 0x04af, 499, /* ү Ү */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8325 | 0x04b1, 499, /* ұ Ұ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8326 | 0x04b3, 499, /* ҳ Ҳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8327 | 0x04b5, 499, /* ҵ Ҵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8328 | 0x04b7, 499, /* ҷ Ҷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8329 | 0x04b9, 499, /* ҹ Ҹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8330 | 0x04bb, 499, /* һ Һ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8331 | 0x04bd, 499, /* ҽ Ҽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8332 | 0x04bf, 499, /* ҿ Ҿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8333 | 0x04c2, 499, /* ӂ Ӂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8334 | 0x04c4, 499, /* ӄ Ӄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8335 | 0x04c8, 499, /* ӈ Ӈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8336 | 0x04cc, 499, /* ӌ Ӌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8337 | 0x04d1, 499, /* ӑ Ӑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8338 | 0x04d3, 499, /* ӓ Ӓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8339 | 0x04d5, 499, /* ӕ Ӕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8340 | 0x04d7, 499, /* ӗ Ӗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8341 | 0x04d9, 499, /* ә Ә */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8342 | 0x04db, 499, /* ӛ Ӛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8343 | 0x04dd, 499, /* ӝ Ӝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8344 | 0x04df, 499, /* ӟ Ӟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8345 | 0x04e1, 499, /* ӡ Ӡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8346 | 0x04e3, 499, /* ӣ Ӣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8347 | 0x04e5, 499, /* ӥ Ӥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8348 | 0x04e7, 499, /* ӧ Ӧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8349 | 0x04e9, 499, /* ө Ө */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8350 | 0x04eb, 499, /* ӫ Ӫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8351 | 0x04ef, 499, /* ӯ Ӯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8352 | 0x04f1, 499, /* ӱ Ӱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8353 | 0x04f3, 499, /* ӳ Ӳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8354 | 0x04f5, 499, /* ӵ Ӵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8355 | 0x04f9, 499, /* ӹ Ӹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8356 | 0x1e01, 499, /* ḁ Ḁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8357 | 0x1e03, 499, /* ḃ Ḃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8358 | 0x1e05, 499, /* ḅ Ḅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8359 | 0x1e07, 499, /* ḇ Ḇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8360 | 0x1e09, 499, /* ḉ Ḉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8361 | 0x1e0b, 499, /* ḋ Ḋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8362 | 0x1e0d, 499, /* ḍ Ḍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8363 | 0x1e0f, 499, /* ḏ Ḏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8364 | 0x1e11, 499, /* ḑ Ḑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8365 | 0x1e13, 499, /* ḓ Ḓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8366 | 0x1e15, 499, /* ḕ Ḕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8367 | 0x1e17, 499, /* ḗ Ḗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8368 | 0x1e19, 499, /* ḙ Ḙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8369 | 0x1e1b, 499, /* ḛ Ḛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8370 | 0x1e1d, 499, /* ḝ Ḝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8371 | 0x1e1f, 499, /* ḟ Ḟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8372 | 0x1e21, 499, /* ḡ Ḡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8373 | 0x1e23, 499, /* ḣ Ḣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8374 | 0x1e25, 499, /* ḥ Ḥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8375 | 0x1e27, 499, /* ḧ Ḧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8376 | 0x1e29, 499, /* ḩ Ḩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8377 | 0x1e2b, 499, /* ḫ Ḫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8378 | 0x1e2d, 499, /* ḭ Ḭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8379 | 0x1e2f, 499, /* ḯ Ḯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8380 | 0x1e31, 499, /* ḱ Ḱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8381 | 0x1e33, 499, /* ḳ Ḳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8382 | 0x1e35, 499, /* ḵ Ḵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8383 | 0x1e37, 499, /* ḷ Ḷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8384 | 0x1e39, 499, /* ḹ Ḹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8385 | 0x1e3b, 499, /* ḻ Ḻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8386 | 0x1e3d, 499, /* ḽ Ḽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8387 | 0x1e3f, 499, /* ḿ Ḿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8388 | 0x1e41, 499, /* ṁ Ṁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8389 | 0x1e43, 499, /* ṃ Ṃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8390 | 0x1e45, 499, /* ṅ Ṅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8391 | 0x1e47, 499, /* ṇ Ṇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8392 | 0x1e49, 499, /* ṉ Ṉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8393 | 0x1e4b, 499, /* ṋ Ṋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8394 | 0x1e4d, 499, /* ṍ Ṍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8395 | 0x1e4f, 499, /* ṏ Ṏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8396 | 0x1e51, 499, /* ṑ Ṑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8397 | 0x1e53, 499, /* ṓ Ṓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8398 | 0x1e55, 499, /* ṕ Ṕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8399 | 0x1e57, 499, /* ṗ Ṗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8400 | 0x1e59, 499, /* ṙ Ṙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8401 | 0x1e5b, 499, /* ṛ Ṛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8402 | 0x1e5d, 499, /* ṝ Ṝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8403 | 0x1e5f, 499, /* ṟ Ṟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8404 | 0x1e61, 499, /* ṡ Ṡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8405 | 0x1e63, 499, /* ṣ Ṣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8406 | 0x1e65, 499, /* ṥ Ṥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8407 | 0x1e67, 499, /* ṧ Ṧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8408 | 0x1e69, 499, /* ṩ Ṩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8409 | 0x1e6b, 499, /* ṫ Ṫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8410 | 0x1e6d, 499, /* ṭ Ṭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8411 | 0x1e6f, 499, /* ṯ Ṯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8412 | 0x1e71, 499, /* ṱ Ṱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8413 | 0x1e73, 499, /* ṳ Ṳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8414 | 0x1e75, 499, /* ṵ Ṵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8415 | 0x1e77, 499, /* ṷ Ṷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8416 | 0x1e79, 499, /* ṹ Ṹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8417 | 0x1e7b, 499, /* ṻ Ṻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8418 | 0x1e7d, 499, /* ṽ Ṽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8419 | 0x1e7f, 499, /* ṿ Ṿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8420 | 0x1e81, 499, /* ẁ Ẁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8421 | 0x1e83, 499, /* ẃ Ẃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8422 | 0x1e85, 499, /* ẅ Ẅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8423 | 0x1e87, 499, /* ẇ Ẇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8424 | 0x1e89, 499, /* ẉ Ẉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8425 | 0x1e8b, 499, /* ẋ Ẋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8426 | 0x1e8d, 499, /* ẍ Ẍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8427 | 0x1e8f, 499, /* ẏ Ẏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8428 | 0x1e91, 499, /* ẑ Ẑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8429 | 0x1e93, 499, /* ẓ Ẓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8430 | 0x1e95, 499, /* ẕ Ẕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8431 | 0x1ea1, 499, /* ạ Ạ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8432 | 0x1ea3, 499, /* ả Ả */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8433 | 0x1ea5, 499, /* ấ Ấ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8434 | 0x1ea7, 499, /* ầ Ầ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8435 | 0x1ea9, 499, /* ẩ Ẩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8436 | 0x1eab, 499, /* ẫ Ẫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8437 | 0x1ead, 499, /* ậ Ậ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8438 | 0x1eaf, 499, /* ắ Ắ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8439 | 0x1eb1, 499, /* ằ Ằ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8440 | 0x1eb3, 499, /* ẳ Ẳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8441 | 0x1eb5, 499, /* ẵ Ẵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8442 | 0x1eb7, 499, /* ặ Ặ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8443 | 0x1eb9, 499, /* ẹ Ẹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8444 | 0x1ebb, 499, /* ẻ Ẻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8445 | 0x1ebd, 499, /* ẽ Ẽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8446 | 0x1ebf, 499, /* ế Ế */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8447 | 0x1ec1, 499, /* ề Ề */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8448 | 0x1ec3, 499, /* ể Ể */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8449 | 0x1ec5, 499, /* ễ Ễ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8450 | 0x1ec7, 499, /* ệ Ệ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8451 | 0x1ec9, 499, /* ỉ Ỉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8452 | 0x1ecb, 499, /* ị Ị */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8453 | 0x1ecd, 499, /* ọ Ọ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8454 | 0x1ecf, 499, /* ỏ Ỏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8455 | 0x1ed1, 499, /* ố Ố */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8456 | 0x1ed3, 499, /* ồ Ồ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8457 | 0x1ed5, 499, /* ổ Ổ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8458 | 0x1ed7, 499, /* ỗ Ỗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8459 | 0x1ed9, 499, /* ộ Ộ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8460 | 0x1edb, 499, /* ớ Ớ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8461 | 0x1edd, 499, /* ờ Ờ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8462 | 0x1edf, 499, /* ở Ở */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8463 | 0x1ee1, 499, /* ỡ Ỡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8464 | 0x1ee3, 499, /* ợ Ợ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8465 | 0x1ee5, 499, /* ụ Ụ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8466 | 0x1ee7, 499, /* ủ Ủ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8467 | 0x1ee9, 499, /* ứ Ứ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8468 | 0x1eeb, 499, /* ừ Ừ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8469 | 0x1eed, 499, /* ử Ử */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8470 | 0x1eef, 499, /* ữ Ữ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8471 | 0x1ef1, 499, /* ự Ự */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8472 | 0x1ef3, 499, /* ỳ Ỳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8473 | 0x1ef5, 499, /* ỵ Ỵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8474 | 0x1ef7, 499, /* ỷ Ỷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8475 | 0x1ef9, 499, /* ỹ Ỹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8476 | 0x1f51, 508, /* ὑ Ὑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8477 | 0x1f53, 508, /* ὓ Ὓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8478 | 0x1f55, 508, /* ὕ Ὕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8479 | 0x1f57, 508, /* ὗ Ὗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8480 | 0x1fb3, 509, /* ᾳ ᾼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8481 | 0x1fc3, 509, /* ῃ ῌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8482 | 0x1fe5, 507, /* ῥ Ῥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8483 | 0x1ff3, 509, /* ῳ ῼ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8484 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8486 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8487 | * upper case ranges |
Marko Mikulicic |
0:c0ecb8bf28eb | 8488 | * 3rd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8489 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8490 | static Rune __tolower2[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8491 | 0x0041, 0x005a, 532, /* A-Z a-z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8492 | 0x00c0, 0x00d6, 532, /* À-Ö à-ö */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8493 | 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8494 | 0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8495 | 0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8496 | 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8497 | 0x0388, 0x038a, 537, /* Έ-Ί έ-ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8498 | 0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8499 | 0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8500 | 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8501 | 0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8502 | 0x040e, 0x040f, 580, /* Ў-Џ ў-џ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8503 | 0x0410, 0x042f, 532, /* А-Я а-я */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8504 | 0x0531, 0x0556, 548, /* Ա-Ֆ ա-ֆ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8505 | 0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8506 | 0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8507 | 0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8508 | 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8509 | 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8510 | 0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8511 | 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8512 | 0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8513 | 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8514 | 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8515 | 0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8516 | 0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8517 | 0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8518 | 0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8519 | 0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8520 | 0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8521 | 0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8522 | 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8523 | 0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8524 | 0x2160, 0x216f, 516, /* Ⅰ-Ⅿ ⅰ-ⅿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8525 | 0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8526 | 0xff21, 0xff3a, 532, /* A-Z a-z */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8527 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8529 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 8530 | * upper case singlets |
Marko Mikulicic |
0:c0ecb8bf28eb | 8531 | * 2nd col is conversion excess 500 |
Marko Mikulicic |
0:c0ecb8bf28eb | 8532 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8533 | static Rune __tolower1[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8534 | 0x0100, 501, /* Ā ā */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8535 | 0x0102, 501, /* Ă ă */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8536 | 0x0104, 501, /* Ą ą */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8537 | 0x0106, 501, /* Ć ć */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8538 | 0x0108, 501, /* Ĉ ĉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8539 | 0x010a, 501, /* Ċ ċ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8540 | 0x010c, 501, /* Č č */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8541 | 0x010e, 501, /* Ď ď */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8542 | 0x0110, 501, /* Đ đ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8543 | 0x0112, 501, /* Ē ē */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8544 | 0x0114, 501, /* Ĕ ĕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8545 | 0x0116, 501, /* Ė ė */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8546 | 0x0118, 501, /* Ę ę */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8547 | 0x011a, 501, /* Ě ě */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8548 | 0x011c, 501, /* Ĝ ĝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8549 | 0x011e, 501, /* Ğ ğ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8550 | 0x0120, 501, /* Ġ ġ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8551 | 0x0122, 501, /* Ģ ģ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8552 | 0x0124, 501, /* Ĥ ĥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8553 | 0x0126, 501, /* Ħ ħ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8554 | 0x0128, 501, /* Ĩ ĩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8555 | 0x012a, 501, /* Ī ī */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8556 | 0x012c, 501, /* Ĭ ĭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8557 | 0x012e, 501, /* Į į */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8558 | 0x0130, 301, /* İ i */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8559 | 0x0132, 501, /* IJ ij */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8560 | 0x0134, 501, /* Ĵ ĵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8561 | 0x0136, 501, /* Ķ ķ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8562 | 0x0139, 501, /* Ĺ ĺ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8563 | 0x013b, 501, /* Ļ ļ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8564 | 0x013d, 501, /* Ľ ľ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8565 | 0x013f, 501, /* Ŀ ŀ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8566 | 0x0141, 501, /* Ł ł */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8567 | 0x0143, 501, /* Ń ń */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8568 | 0x0145, 501, /* Ņ ņ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8569 | 0x0147, 501, /* Ň ň */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8570 | 0x014a, 501, /* Ŋ ŋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8571 | 0x014c, 501, /* Ō ō */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8572 | 0x014e, 501, /* Ŏ ŏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8573 | 0x0150, 501, /* Ő ő */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8574 | 0x0152, 501, /* Œ œ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8575 | 0x0154, 501, /* Ŕ ŕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8576 | 0x0156, 501, /* Ŗ ŗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8577 | 0x0158, 501, /* Ř ř */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8578 | 0x015a, 501, /* Ś ś */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8579 | 0x015c, 501, /* Ŝ ŝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8580 | 0x015e, 501, /* Ş ş */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8581 | 0x0160, 501, /* Š š */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8582 | 0x0162, 501, /* Ţ ţ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8583 | 0x0164, 501, /* Ť ť */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8584 | 0x0166, 501, /* Ŧ ŧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8585 | 0x0168, 501, /* Ũ ũ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8586 | 0x016a, 501, /* Ū ū */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8587 | 0x016c, 501, /* Ŭ ŭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8588 | 0x016e, 501, /* Ů ů */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8589 | 0x0170, 501, /* Ű ű */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8590 | 0x0172, 501, /* Ų ų */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8591 | 0x0174, 501, /* Ŵ ŵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8592 | 0x0176, 501, /* Ŷ ŷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8593 | 0x0178, 379, /* Ÿ ÿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8594 | 0x0179, 501, /* Ź ź */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8595 | 0x017b, 501, /* Ż ż */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8596 | 0x017d, 501, /* Ž ž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8597 | 0x0181, 710, /* Ɓ ɓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8598 | 0x0182, 501, /* Ƃ ƃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8599 | 0x0184, 501, /* Ƅ ƅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8600 | 0x0186, 706, /* Ɔ ɔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8601 | 0x0187, 501, /* Ƈ ƈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8602 | 0x018b, 501, /* Ƌ ƌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8603 | 0x0190, 703, /* Ɛ ɛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8604 | 0x0191, 501, /* Ƒ ƒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8605 | 0x0193, 705, /* Ɠ ɠ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8606 | 0x0194, 707, /* Ɣ ɣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8607 | 0x0196, 711, /* Ɩ ɩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8608 | 0x0197, 709, /* Ɨ ɨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8609 | 0x0198, 501, /* Ƙ ƙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8610 | 0x019c, 711, /* Ɯ ɯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8611 | 0x019d, 713, /* Ɲ ɲ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8612 | 0x01a0, 501, /* Ơ ơ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8613 | 0x01a2, 501, /* Ƣ ƣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8614 | 0x01a4, 501, /* Ƥ ƥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8615 | 0x01a7, 501, /* Ƨ ƨ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8616 | 0x01a9, 718, /* Ʃ ʃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8617 | 0x01ac, 501, /* Ƭ ƭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8618 | 0x01ae, 718, /* Ʈ ʈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8619 | 0x01af, 501, /* Ư ư */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8620 | 0x01b3, 501, /* Ƴ ƴ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8621 | 0x01b5, 501, /* Ƶ ƶ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8622 | 0x01b7, 719, /* Ʒ ʒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8623 | 0x01b8, 501, /* Ƹ ƹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8624 | 0x01bc, 501, /* Ƽ ƽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8625 | 0x01c4, 502, /* DŽ dž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8626 | 0x01c5, 501, /* Dž dž */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8627 | 0x01c7, 502, /* LJ lj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8628 | 0x01c8, 501, /* Lj lj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8629 | 0x01ca, 502, /* NJ nj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8630 | 0x01cb, 501, /* Nj nj */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8631 | 0x01cd, 501, /* Ǎ ǎ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8632 | 0x01cf, 501, /* Ǐ ǐ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8633 | 0x01d1, 501, /* Ǒ ǒ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8634 | 0x01d3, 501, /* Ǔ ǔ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8635 | 0x01d5, 501, /* Ǖ ǖ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8636 | 0x01d7, 501, /* Ǘ ǘ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8637 | 0x01d9, 501, /* Ǚ ǚ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8638 | 0x01db, 501, /* Ǜ ǜ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8639 | 0x01de, 501, /* Ǟ ǟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8640 | 0x01e0, 501, /* Ǡ ǡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8641 | 0x01e2, 501, /* Ǣ ǣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8642 | 0x01e4, 501, /* Ǥ ǥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8643 | 0x01e6, 501, /* Ǧ ǧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8644 | 0x01e8, 501, /* Ǩ ǩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8645 | 0x01ea, 501, /* Ǫ ǫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8646 | 0x01ec, 501, /* Ǭ ǭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8647 | 0x01ee, 501, /* Ǯ ǯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8648 | 0x01f1, 502, /* DZ dz */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8649 | 0x01f2, 501, /* Dz dz */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8650 | 0x01f4, 501, /* Ǵ ǵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8651 | 0x01fa, 501, /* Ǻ ǻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8652 | 0x01fc, 501, /* Ǽ ǽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8653 | 0x01fe, 501, /* Ǿ ǿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8654 | 0x0200, 501, /* Ȁ ȁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8655 | 0x0202, 501, /* Ȃ ȃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8656 | 0x0204, 501, /* Ȅ ȅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8657 | 0x0206, 501, /* Ȇ ȇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8658 | 0x0208, 501, /* Ȉ ȉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8659 | 0x020a, 501, /* Ȋ ȋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8660 | 0x020c, 501, /* Ȍ ȍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8661 | 0x020e, 501, /* Ȏ ȏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8662 | 0x0210, 501, /* Ȑ ȑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8663 | 0x0212, 501, /* Ȓ ȓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8664 | 0x0214, 501, /* Ȕ ȕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8665 | 0x0216, 501, /* Ȗ ȗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8666 | 0x0386, 538, /* Ά ά */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8667 | 0x038c, 564, /* Ό ό */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8668 | 0x03e2, 501, /* Ϣ ϣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8669 | 0x03e4, 501, /* Ϥ ϥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8670 | 0x03e6, 501, /* Ϧ ϧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8671 | 0x03e8, 501, /* Ϩ ϩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8672 | 0x03ea, 501, /* Ϫ ϫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8673 | 0x03ec, 501, /* Ϭ ϭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8674 | 0x03ee, 501, /* Ϯ ϯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8675 | 0x0460, 501, /* Ѡ ѡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8676 | 0x0462, 501, /* Ѣ ѣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8677 | 0x0464, 501, /* Ѥ ѥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8678 | 0x0466, 501, /* Ѧ ѧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8679 | 0x0468, 501, /* Ѩ ѩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8680 | 0x046a, 501, /* Ѫ ѫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8681 | 0x046c, 501, /* Ѭ ѭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8682 | 0x046e, 501, /* Ѯ ѯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8683 | 0x0470, 501, /* Ѱ ѱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8684 | 0x0472, 501, /* Ѳ ѳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8685 | 0x0474, 501, /* Ѵ ѵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8686 | 0x0476, 501, /* Ѷ ѷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8687 | 0x0478, 501, /* Ѹ ѹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8688 | 0x047a, 501, /* Ѻ ѻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8689 | 0x047c, 501, /* Ѽ ѽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8690 | 0x047e, 501, /* Ѿ ѿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8691 | 0x0480, 501, /* Ҁ ҁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8692 | 0x0490, 501, /* Ґ ґ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8693 | 0x0492, 501, /* Ғ ғ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8694 | 0x0494, 501, /* Ҕ ҕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8695 | 0x0496, 501, /* Җ җ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8696 | 0x0498, 501, /* Ҙ ҙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8697 | 0x049a, 501, /* Қ қ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8698 | 0x049c, 501, /* Ҝ ҝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8699 | 0x049e, 501, /* Ҟ ҟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8700 | 0x04a0, 501, /* Ҡ ҡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8701 | 0x04a2, 501, /* Ң ң */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8702 | 0x04a4, 501, /* Ҥ ҥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8703 | 0x04a6, 501, /* Ҧ ҧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8704 | 0x04a8, 501, /* Ҩ ҩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8705 | 0x04aa, 501, /* Ҫ ҫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8706 | 0x04ac, 501, /* Ҭ ҭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8707 | 0x04ae, 501, /* Ү ү */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8708 | 0x04b0, 501, /* Ұ ұ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8709 | 0x04b2, 501, /* Ҳ ҳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8710 | 0x04b4, 501, /* Ҵ ҵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8711 | 0x04b6, 501, /* Ҷ ҷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8712 | 0x04b8, 501, /* Ҹ ҹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8713 | 0x04ba, 501, /* Һ һ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8714 | 0x04bc, 501, /* Ҽ ҽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8715 | 0x04be, 501, /* Ҿ ҿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8716 | 0x04c1, 501, /* Ӂ ӂ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8717 | 0x04c3, 501, /* Ӄ ӄ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8718 | 0x04c7, 501, /* Ӈ ӈ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8719 | 0x04cb, 501, /* Ӌ ӌ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8720 | 0x04d0, 501, /* Ӑ ӑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8721 | 0x04d2, 501, /* Ӓ ӓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8722 | 0x04d4, 501, /* Ӕ ӕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8723 | 0x04d6, 501, /* Ӗ ӗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8724 | 0x04d8, 501, /* Ә ә */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8725 | 0x04da, 501, /* Ӛ ӛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8726 | 0x04dc, 501, /* Ӝ ӝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8727 | 0x04de, 501, /* Ӟ ӟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8728 | 0x04e0, 501, /* Ӡ ӡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8729 | 0x04e2, 501, /* Ӣ ӣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8730 | 0x04e4, 501, /* Ӥ ӥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8731 | 0x04e6, 501, /* Ӧ ӧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8732 | 0x04e8, 501, /* Ө ө */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8733 | 0x04ea, 501, /* Ӫ ӫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8734 | 0x04ee, 501, /* Ӯ ӯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8735 | 0x04f0, 501, /* Ӱ ӱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8736 | 0x04f2, 501, /* Ӳ ӳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8737 | 0x04f4, 501, /* Ӵ ӵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8738 | 0x04f8, 501, /* Ӹ ӹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8739 | 0x1e00, 501, /* Ḁ ḁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8740 | 0x1e02, 501, /* Ḃ ḃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8741 | 0x1e04, 501, /* Ḅ ḅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8742 | 0x1e06, 501, /* Ḇ ḇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8743 | 0x1e08, 501, /* Ḉ ḉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8744 | 0x1e0a, 501, /* Ḋ ḋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8745 | 0x1e0c, 501, /* Ḍ ḍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8746 | 0x1e0e, 501, /* Ḏ ḏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8747 | 0x1e10, 501, /* Ḑ ḑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8748 | 0x1e12, 501, /* Ḓ ḓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8749 | 0x1e14, 501, /* Ḕ ḕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8750 | 0x1e16, 501, /* Ḗ ḗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8751 | 0x1e18, 501, /* Ḙ ḙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8752 | 0x1e1a, 501, /* Ḛ ḛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8753 | 0x1e1c, 501, /* Ḝ ḝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8754 | 0x1e1e, 501, /* Ḟ ḟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8755 | 0x1e20, 501, /* Ḡ ḡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8756 | 0x1e22, 501, /* Ḣ ḣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8757 | 0x1e24, 501, /* Ḥ ḥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8758 | 0x1e26, 501, /* Ḧ ḧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8759 | 0x1e28, 501, /* Ḩ ḩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8760 | 0x1e2a, 501, /* Ḫ ḫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8761 | 0x1e2c, 501, /* Ḭ ḭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8762 | 0x1e2e, 501, /* Ḯ ḯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8763 | 0x1e30, 501, /* Ḱ ḱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8764 | 0x1e32, 501, /* Ḳ ḳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8765 | 0x1e34, 501, /* Ḵ ḵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8766 | 0x1e36, 501, /* Ḷ ḷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8767 | 0x1e38, 501, /* Ḹ ḹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8768 | 0x1e3a, 501, /* Ḻ ḻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8769 | 0x1e3c, 501, /* Ḽ ḽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8770 | 0x1e3e, 501, /* Ḿ ḿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8771 | 0x1e40, 501, /* Ṁ ṁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8772 | 0x1e42, 501, /* Ṃ ṃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8773 | 0x1e44, 501, /* Ṅ ṅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8774 | 0x1e46, 501, /* Ṇ ṇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8775 | 0x1e48, 501, /* Ṉ ṉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8776 | 0x1e4a, 501, /* Ṋ ṋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8777 | 0x1e4c, 501, /* Ṍ ṍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8778 | 0x1e4e, 501, /* Ṏ ṏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8779 | 0x1e50, 501, /* Ṑ ṑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8780 | 0x1e52, 501, /* Ṓ ṓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8781 | 0x1e54, 501, /* Ṕ ṕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8782 | 0x1e56, 501, /* Ṗ ṗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8783 | 0x1e58, 501, /* Ṙ ṙ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8784 | 0x1e5a, 501, /* Ṛ ṛ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8785 | 0x1e5c, 501, /* Ṝ ṝ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8786 | 0x1e5e, 501, /* Ṟ ṟ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8787 | 0x1e60, 501, /* Ṡ ṡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8788 | 0x1e62, 501, /* Ṣ ṣ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8789 | 0x1e64, 501, /* Ṥ ṥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8790 | 0x1e66, 501, /* Ṧ ṧ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8791 | 0x1e68, 501, /* Ṩ ṩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8792 | 0x1e6a, 501, /* Ṫ ṫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8793 | 0x1e6c, 501, /* Ṭ ṭ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8794 | 0x1e6e, 501, /* Ṯ ṯ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8795 | 0x1e70, 501, /* Ṱ ṱ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8796 | 0x1e72, 501, /* Ṳ ṳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8797 | 0x1e74, 501, /* Ṵ ṵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8798 | 0x1e76, 501, /* Ṷ ṷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8799 | 0x1e78, 501, /* Ṹ ṹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8800 | 0x1e7a, 501, /* Ṻ ṻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8801 | 0x1e7c, 501, /* Ṽ ṽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8802 | 0x1e7e, 501, /* Ṿ ṿ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8803 | 0x1e80, 501, /* Ẁ ẁ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8804 | 0x1e82, 501, /* Ẃ ẃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8805 | 0x1e84, 501, /* Ẅ ẅ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8806 | 0x1e86, 501, /* Ẇ ẇ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8807 | 0x1e88, 501, /* Ẉ ẉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8808 | 0x1e8a, 501, /* Ẋ ẋ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8809 | 0x1e8c, 501, /* Ẍ ẍ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8810 | 0x1e8e, 501, /* Ẏ ẏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8811 | 0x1e90, 501, /* Ẑ ẑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8812 | 0x1e92, 501, /* Ẓ ẓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8813 | 0x1e94, 501, /* Ẕ ẕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8814 | 0x1ea0, 501, /* Ạ ạ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8815 | 0x1ea2, 501, /* Ả ả */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8816 | 0x1ea4, 501, /* Ấ ấ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8817 | 0x1ea6, 501, /* Ầ ầ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8818 | 0x1ea8, 501, /* Ẩ ẩ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8819 | 0x1eaa, 501, /* Ẫ ẫ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8820 | 0x1eac, 501, /* Ậ ậ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8821 | 0x1eae, 501, /* Ắ ắ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8822 | 0x1eb0, 501, /* Ằ ằ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8823 | 0x1eb2, 501, /* Ẳ ẳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8824 | 0x1eb4, 501, /* Ẵ ẵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8825 | 0x1eb6, 501, /* Ặ ặ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8826 | 0x1eb8, 501, /* Ẹ ẹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8827 | 0x1eba, 501, /* Ẻ ẻ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8828 | 0x1ebc, 501, /* Ẽ ẽ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8829 | 0x1ebe, 501, /* Ế ế */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8830 | 0x1ec0, 501, /* Ề ề */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8831 | 0x1ec2, 501, /* Ể ể */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8832 | 0x1ec4, 501, /* Ễ ễ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8833 | 0x1ec6, 501, /* Ệ ệ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8834 | 0x1ec8, 501, /* Ỉ ỉ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8835 | 0x1eca, 501, /* Ị ị */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8836 | 0x1ecc, 501, /* Ọ ọ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8837 | 0x1ece, 501, /* Ỏ ỏ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8838 | 0x1ed0, 501, /* Ố ố */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8839 | 0x1ed2, 501, /* Ồ ồ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8840 | 0x1ed4, 501, /* Ổ ổ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8841 | 0x1ed6, 501, /* Ỗ ỗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8842 | 0x1ed8, 501, /* Ộ ộ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8843 | 0x1eda, 501, /* Ớ ớ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8844 | 0x1edc, 501, /* Ờ ờ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8845 | 0x1ede, 501, /* Ở ở */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8846 | 0x1ee0, 501, /* Ỡ ỡ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8847 | 0x1ee2, 501, /* Ợ ợ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8848 | 0x1ee4, 501, /* Ụ ụ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8849 | 0x1ee6, 501, /* Ủ ủ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8850 | 0x1ee8, 501, /* Ứ ứ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8851 | 0x1eea, 501, /* Ừ ừ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8852 | 0x1eec, 501, /* Ử ử */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8853 | 0x1eee, 501, /* Ữ ữ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8854 | 0x1ef0, 501, /* Ự ự */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8855 | 0x1ef2, 501, /* Ỳ ỳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8856 | 0x1ef4, 501, /* Ỵ ỵ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8857 | 0x1ef6, 501, /* Ỷ ỷ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8858 | 0x1ef8, 501, /* Ỹ ỹ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8859 | 0x1f59, 492, /* Ὑ ὑ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8860 | 0x1f5b, 492, /* Ὓ ὓ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8861 | 0x1f5d, 492, /* Ὕ ὕ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8862 | 0x1f5f, 492, /* Ὗ ὗ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8863 | 0x1fbc, 491, /* ᾼ ᾳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8864 | 0x1fcc, 491, /* ῌ ῃ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8865 | 0x1fec, 493, /* Ῥ ῥ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8866 | 0x1ffc, 491, /* ῼ ῳ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8867 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8869 | static Rune *rune_bsearch(Rune c, Rune *t, int n, int ne) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8870 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8871 | int m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8873 | while (n > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8874 | m = n / 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8875 | p = t + m * ne; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8876 | if (c >= p[0]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8877 | t = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8878 | n = n - m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8879 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 8880 | n = m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8881 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8882 | if (n && c >= t[0]) return t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8883 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8884 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8886 | Rune tolowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8887 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8889 | p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8890 | if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8891 | p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8892 | if (p && c == p[0]) return c + p[1] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8893 | return c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8894 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8895 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8896 | Rune toupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8897 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8899 | p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8900 | if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8901 | p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8902 | if (p && c == p[0]) return c + p[1] - 500; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8903 | return c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8904 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8906 | int islowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8907 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8909 | p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8910 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8911 | p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8912 | if (p && c == p[0]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8913 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8914 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8916 | int isupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8917 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8918 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8919 | p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8920 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8921 | p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8922 | if (p && c == p[0]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8923 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8924 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8926 | int isdigitrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8927 | return c >= '0' && c <= '9'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8928 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8930 | int isnewline(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8931 | return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8932 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8934 | int iswordchar(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8935 | return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') || |
Marko Mikulicic |
0:c0ecb8bf28eb | 8936 | (c >= 'A' && c <= 'Z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8937 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8939 | int isalpharune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8940 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8942 | if (isupperrune(c) || islowerrune(c)) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8943 | p = rune_bsearch(c, __alpha2, nelem(__alpha2) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8944 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8945 | p = rune_bsearch(c, __alpha1, nelem(__alpha1), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8946 | if (p && c == p[0]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8947 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8948 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8950 | int isspacerune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8951 | Rune *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8953 | p = rune_bsearch(c, __space2, nelem(__space2) / 2, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8954 | if (p && c >= p[0] && c <= p[1]) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8955 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8956 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8957 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8958 | #else /* CS_ENABLE_UTF8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 8959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8960 | int chartorune(Rune *rune, const char *str) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8961 | *rune = *(uchar *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8962 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8963 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8964 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8965 | int fullrune(const char *str, int n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8966 | (void) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8967 | return (n <= 0) ? 0 : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8968 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8970 | int isdigitrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8971 | return isdigit(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8974 | int isnewline(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8975 | return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8976 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8978 | int iswordchar(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8979 | return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') || |
Marko Mikulicic |
0:c0ecb8bf28eb | 8980 | (c >= 'A' && c <= 'Z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8983 | int isalpharune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8984 | return isalpha(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8985 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8986 | int islowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8987 | return islower(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8988 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8989 | int isspacerune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8990 | return isspace(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8991 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8992 | int isupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8993 | return isupper(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 8994 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 8995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 8996 | int runetochar(char *str, Rune *rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 8997 | str[0] = (char) *rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8998 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 8999 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9000 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9001 | Rune tolowerrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9002 | return tolower(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9003 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9004 | Rune toupperrune(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9005 | return toupper(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9007 | int utfnlen(const char *s, long m) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9008 | (void) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9009 | return (int) c_strnlen(s, (size_t) m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9010 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9012 | const char *utfnshift(const char *s, long m) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9013 | return s + m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9014 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9015 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9016 | #endif /* CS_ENABLE_UTF8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9018 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9019 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9020 | #line 1 "common/base64.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9021 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9022 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9023 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 9024 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 9025 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9027 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 9028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9029 | /* Amalgamated: #include "common/base64.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9030 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9031 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9032 | /* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9033 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9034 | #define NUM_UPPERCASES ('Z' - 'A' + 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9035 | #define NUM_LETTERS (NUM_UPPERCASES * 2) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9036 | #define NUM_DIGITS ('9' - '0' + 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9038 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9039 | * Emit a base64 code char. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9040 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 9041 | * Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps |
Marko Mikulicic |
0:c0ecb8bf28eb | 9042 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9043 | static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9044 | if (v < NUM_UPPERCASES) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9045 | ctx->b64_putc(v + 'A', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9046 | } else if (v < (NUM_LETTERS)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9047 | ctx->b64_putc(v - NUM_UPPERCASES + 'a', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9048 | } else if (v < (NUM_LETTERS + NUM_DIGITS)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9049 | ctx->b64_putc(v - NUM_LETTERS + '0', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9050 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9051 | ctx->b64_putc(v - NUM_LETTERS - NUM_DIGITS == 0 ? '+' : '/', |
Marko Mikulicic |
0:c0ecb8bf28eb | 9052 | ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9053 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9054 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9056 | static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9057 | int a, b, c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9059 | a = ctx->chunk[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9060 | b = ctx->chunk[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9061 | c = ctx->chunk[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9063 | cs_base64_emit_code(ctx, a >> 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9064 | cs_base64_emit_code(ctx, ((a & 3) << 4) | (b >> 4)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9065 | if (ctx->chunk_size > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9066 | cs_base64_emit_code(ctx, (b & 15) << 2 | (c >> 6)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9068 | if (ctx->chunk_size > 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9069 | cs_base64_emit_code(ctx, c & 63); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9070 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9071 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9073 | void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9074 | void *user_data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9075 | ctx->chunk_size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9076 | ctx->b64_putc = b64_putc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9077 | ctx->user_data = user_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9078 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9079 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9080 | void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9081 | const unsigned char *src = (const unsigned char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9082 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9083 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9084 | ctx->chunk[ctx->chunk_size++] = src[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9085 | if (ctx->chunk_size == 3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9086 | cs_base64_emit_chunk(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9087 | ctx->chunk_size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9089 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9090 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9091 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9092 | void cs_base64_finish(struct cs_base64_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9093 | if (ctx->chunk_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9094 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9095 | memset(&ctx->chunk[ctx->chunk_size], 0, 3 - ctx->chunk_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9096 | cs_base64_emit_chunk(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9097 | for (i = 0; i < (3 - ctx->chunk_size); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9098 | ctx->b64_putc('=', ctx->user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9099 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9101 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9103 | #define BASE64_ENCODE_BODY \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9104 | static const char *b64 = \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9105 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9106 | int i, j, a, b, c; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9107 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9108 | for (i = j = 0; i < src_len; i += 3) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9109 | a = src[i]; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9110 | b = i + 1 >= src_len ? 0 : src[i + 1]; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9111 | c = i + 2 >= src_len ? 0 : src[i + 2]; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9112 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9113 | BASE64_OUT(b64[a >> 2]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9114 | BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9115 | if (i + 1 < src_len) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9116 | BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9117 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9118 | if (i + 2 < src_len) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9119 | BASE64_OUT(b64[c & 63]); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9120 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9121 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9122 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9123 | while (j % 4 != 0) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9124 | BASE64_OUT('='); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9125 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9126 | BASE64_FLUSH() |
Marko Mikulicic |
0:c0ecb8bf28eb | 9127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9128 | #define BASE64_OUT(ch) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9129 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9130 | dst[j++] = (ch); \ |
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 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9135 | dst[j++] = '\0'; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9136 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9138 | void cs_base64_encode(const unsigned char *src, int src_len, char *dst) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9139 | BASE64_ENCODE_BODY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9140 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9142 | #undef BASE64_OUT |
Marko Mikulicic |
0:c0ecb8bf28eb | 9143 | #undef BASE64_FLUSH |
Marko Mikulicic |
0:c0ecb8bf28eb | 9144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9145 | #ifndef CS_DISABLE_STDIO |
Marko Mikulicic |
0:c0ecb8bf28eb | 9146 | #define BASE64_OUT(ch) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9147 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9148 | fprintf(f, "%c", (ch)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9149 | j++; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9150 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9151 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9152 | #define BASE64_FLUSH() |
Marko Mikulicic |
0:c0ecb8bf28eb | 9153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9154 | void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9155 | BASE64_ENCODE_BODY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9156 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9158 | #undef BASE64_OUT |
Marko Mikulicic |
0:c0ecb8bf28eb | 9159 | #undef BASE64_FLUSH |
Marko Mikulicic |
0:c0ecb8bf28eb | 9160 | #endif /* !CS_DISABLE_STDIO */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9162 | /* Convert one byte of encoded base64 input stream to 6-bit chunk */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9163 | static unsigned char from_b64(unsigned char ch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9164 | /* Inverse lookup map */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9165 | static const unsigned char tab[128] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9166 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9167 | 255, 255, 255, 255, /* 0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9168 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9169 | 255, 255, 255, 255, /* 8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9170 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9171 | 255, 255, 255, 255, /* 16 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9172 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9173 | 255, 255, 255, 255, /* 24 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9174 | 255, 255, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9175 | 255, 255, 255, 255, /* 32 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9176 | 255, 255, 255, 62, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9177 | 255, 255, 255, 63, /* 40 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9178 | 52, 53, 54, 55, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9179 | 56, 57, 58, 59, /* 48 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9180 | 60, 61, 255, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9181 | 255, 200, 255, 255, /* 56 '=' is 200, on index 61 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9182 | 255, 0, 1, 2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9183 | 3, 4, 5, 6, /* 64 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9184 | 7, 8, 9, 10, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9185 | 11, 12, 13, 14, /* 72 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9186 | 15, 16, 17, 18, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9187 | 19, 20, 21, 22, /* 80 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9188 | 23, 24, 25, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9189 | 255, 255, 255, 255, /* 88 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9190 | 255, 26, 27, 28, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9191 | 29, 30, 31, 32, /* 96 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9192 | 33, 34, 35, 36, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9193 | 37, 38, 39, 40, /* 104 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9194 | 41, 42, 43, 44, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9195 | 45, 46, 47, 48, /* 112 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9196 | 49, 50, 51, 255, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9197 | 255, 255, 255, 255, /* 120 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9198 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9199 | return tab[ch & 127]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9201 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9202 | int cs_base64_decode(const unsigned char *s, int len, char *dst) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9203 | unsigned char a, b, c, d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9204 | int orig_len = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9205 | while (len >= 4 && (a = from_b64(s[0])) != 255 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 9206 | (b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 9207 | (d = from_b64(s[3])) != 255) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9208 | s += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9209 | len -= 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9210 | if (a == 200 || b == 200) break; /* '=' can't be there */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9211 | *dst++ = a << 2 | b >> 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9212 | if (c == 200) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9213 | *dst++ = b << 4 | c >> 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9214 | if (d == 200) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9215 | *dst++ = c << 6 | d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9216 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9217 | *dst = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9218 | return orig_len - len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9219 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9220 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9221 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9222 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9223 | #line 1 "common/md5.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9224 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9225 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9226 | * This code implements the MD5 message-digest algorithm. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9227 | * The algorithm is due to Ron Rivest. This code was |
Marko Mikulicic |
0:c0ecb8bf28eb | 9228 | * written by Colin Plumb in 1993, no copyright is claimed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9229 | * This code is in the public domain; do with it what you wish. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9230 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 9231 | * Equivalent code is available from RSA Data Security, Inc. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9232 | * This code has been tested against that, and is equivalent, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9233 | * except that you don't need to include two pages of legalese |
Marko Mikulicic |
0:c0ecb8bf28eb | 9234 | * with every copy. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9235 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 9236 | * To compute the message digest of a chunk of bytes, declare an |
Marko Mikulicic |
0:c0ecb8bf28eb | 9237 | * MD5Context structure, pass it to MD5Init, call MD5Update as |
Marko Mikulicic |
0:c0ecb8bf28eb | 9238 | * needed on buffers full of bytes, and then call MD5Final, which |
Marko Mikulicic |
0:c0ecb8bf28eb | 9239 | * will fill a supplied 16-byte array with the digest. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9240 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9242 | #if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9244 | /* Amalgamated: #include "common/md5.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9245 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9246 | #ifndef CS_ENABLE_NATIVE_MD5 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9247 | static void byteReverse(unsigned char *buf, unsigned longs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9248 | /* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9249 | #if BYTE_ORDER == BIG_ENDIAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 9250 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9251 | uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9252 | ((unsigned) buf[1] << 8 | buf[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9253 | *(uint32_t *) buf = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9254 | buf += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9255 | } while (--longs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9256 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 9257 | (void) buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9258 | (void) longs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9259 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9260 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9262 | #define F1(x, y, z) (z ^ (x & (y ^ z))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9263 | #define F2(x, y, z) F1(z, x, y) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9264 | #define F3(x, y, z) (x ^ y ^ z) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9265 | #define F4(x, y, z) (y ^ (x | ~z)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9267 | #define MD5STEP(f, w, x, y, z, data, s) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9268 | (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9270 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9271 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious |
Marko Mikulicic |
0:c0ecb8bf28eb | 9272 | * initialization constants. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9273 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9274 | void MD5_Init(MD5_CTX *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9275 | ctx->buf[0] = 0x67452301; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9276 | ctx->buf[1] = 0xefcdab89; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9277 | ctx->buf[2] = 0x98badcfe; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9278 | ctx->buf[3] = 0x10325476; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9280 | ctx->bits[0] = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9281 | ctx->bits[1] = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9282 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9284 | static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9285 | register uint32_t a, b, c, d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9286 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9287 | a = buf[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9288 | b = buf[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9289 | c = buf[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9290 | d = buf[3]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9292 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9293 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9294 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9295 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9296 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9297 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9298 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9299 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9300 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9301 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9302 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9303 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9304 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9305 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9306 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9307 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9309 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9310 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9311 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9312 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9313 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9314 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9315 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9316 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9317 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9318 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9319 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9320 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9321 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9322 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9323 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9324 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9325 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9326 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9327 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9328 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9329 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9330 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9331 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9332 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9333 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9334 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9335 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9336 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9337 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9338 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9339 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9340 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9341 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9343 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9344 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9345 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9346 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9347 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9348 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9349 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9350 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9351 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9352 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9353 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9354 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9355 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9356 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9357 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9358 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9360 | buf[0] += a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9361 | buf[1] += b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9362 | buf[2] += c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9363 | buf[3] += d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9366 | void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9367 | uint32_t t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9369 | t = ctx->bits[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9370 | if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9371 | ctx->bits[1] += (uint32_t) len >> 29; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9373 | t = (t >> 3) & 0x3f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9375 | if (t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9376 | unsigned char *p = (unsigned char *) ctx->in + t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9378 | t = 64 - t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9379 | if (len < t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9380 | memcpy(p, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9381 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9382 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9383 | memcpy(p, buf, t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9384 | byteReverse(ctx->in, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9385 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9386 | buf += t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9387 | len -= t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9390 | while (len >= 64) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9391 | memcpy(ctx->in, buf, 64); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9392 | byteReverse(ctx->in, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9393 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9394 | buf += 64; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9395 | len -= 64; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9396 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9398 | memcpy(ctx->in, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9399 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9400 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9401 | void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9402 | unsigned count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9403 | unsigned char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9404 | uint32_t *a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9406 | count = (ctx->bits[0] >> 3) & 0x3F; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9408 | p = ctx->in + count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9409 | *p++ = 0x80; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9410 | count = 64 - 1 - count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9411 | if (count < 8) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9412 | memset(p, 0, count); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9413 | byteReverse(ctx->in, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9414 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9415 | memset(ctx->in, 0, 56); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9416 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9417 | memset(p, 0, count - 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9418 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9419 | byteReverse(ctx->in, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9421 | a = (uint32_t *) ctx->in; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9422 | a[14] = ctx->bits[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9423 | a[15] = ctx->bits[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9425 | MD5Transform(ctx->buf, (uint32_t *) ctx->in); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9426 | byteReverse((unsigned char *) ctx->buf, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9427 | memcpy(digest, ctx->buf, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9428 | memset((char *) ctx, 0, sizeof(*ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9429 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9430 | #endif /* CS_ENABLE_NATIVE_MD5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9432 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9433 | * Stringify binary data. Output buffer size must be 2 * size_of_input + 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9434 | * because each byte of input takes 2 bytes in string representation |
Marko Mikulicic |
0:c0ecb8bf28eb | 9435 | * plus 1 byte for the terminating \0 character. |
Marko Mikulicic |
0:c0ecb8bf28eb | 9436 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9437 | void cs_to_hex(char *to, const unsigned char *p, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9438 | static const char *hex = "0123456789abcdef"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9440 | for (; len--; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9441 | *to++ = hex[p[0] >> 4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9442 | *to++ = hex[p[0] & 0x0f]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9444 | *to = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9445 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9446 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9447 | char *cs_md5(char buf[33], ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9448 | unsigned char hash[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9449 | const unsigned char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9450 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9451 | MD5_CTX ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9453 | MD5_Init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9455 | va_start(ap, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9456 | while ((p = va_arg(ap, const unsigned char *) ) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9457 | size_t len = va_arg(ap, size_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9458 | MD5_Update(&ctx, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9459 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9460 | va_end(ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9462 | MD5_Final(hash, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9463 | cs_to_hex(buf, hash, sizeof(hash)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9465 | return buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9466 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9467 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9468 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9469 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9470 | #line 1 "common/sha1.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9471 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9472 | /* Copyright(c) By Steve Reid <steve@edmweb.com> */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9473 | /* 100% Public Domain */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9475 | #if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9477 | /* Amalgamated: #include "common/sha1.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9478 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9479 | #define SHA1HANDSOFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 9480 | #if defined(__sun) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9481 | /* Amalgamated: #include "common/solarisfixes.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9482 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9484 | union char64long16 { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9485 | unsigned char c[64]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9486 | uint32_t l[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9487 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9489 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9491 | static uint32_t blk0(union char64long16 *block, int i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9492 | /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9493 | #if BYTE_ORDER == LITTLE_ENDIAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 9494 | block->l[i] = |
Marko Mikulicic |
0:c0ecb8bf28eb | 9495 | (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9496 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9497 | return block->l[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9498 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9499 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9500 | /* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9501 | #undef blk |
Marko Mikulicic |
0:c0ecb8bf28eb | 9502 | #undef R0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9503 | #undef R1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9504 | #undef R2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9505 | #undef R3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9506 | #undef R4 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9508 | #define blk(i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9509 | (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9510 | block->l[(i + 2) & 15] ^ block->l[i & 15], \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9511 | 1)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9512 | #define R0(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9513 | z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9514 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9515 | #define R1(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9516 | z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9517 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9518 | #define R2(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9519 | z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9520 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9521 | #define R3(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9522 | z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9523 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9524 | #define R4(v, w, x, y, z, i) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9525 | z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9526 | w = rol(w, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9528 | void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9529 | uint32_t a, b, c, d, e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9530 | union char64long16 block[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9532 | memcpy(block, buffer, 64); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9533 | a = state[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9534 | b = state[1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9535 | c = state[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9536 | d = state[3]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9537 | e = state[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9538 | R0(a, b, c, d, e, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9539 | R0(e, a, b, c, d, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9540 | R0(d, e, a, b, c, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9541 | R0(c, d, e, a, b, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9542 | R0(b, c, d, e, a, 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9543 | R0(a, b, c, d, e, 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9544 | R0(e, a, b, c, d, 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9545 | R0(d, e, a, b, c, 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9546 | R0(c, d, e, a, b, 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9547 | R0(b, c, d, e, a, 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9548 | R0(a, b, c, d, e, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9549 | R0(e, a, b, c, d, 11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9550 | R0(d, e, a, b, c, 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9551 | R0(c, d, e, a, b, 13); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9552 | R0(b, c, d, e, a, 14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9553 | R0(a, b, c, d, e, 15); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9554 | R1(e, a, b, c, d, 16); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9555 | R1(d, e, a, b, c, 17); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9556 | R1(c, d, e, a, b, 18); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9557 | R1(b, c, d, e, a, 19); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9558 | R2(a, b, c, d, e, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9559 | R2(e, a, b, c, d, 21); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9560 | R2(d, e, a, b, c, 22); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9561 | R2(c, d, e, a, b, 23); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9562 | R2(b, c, d, e, a, 24); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9563 | R2(a, b, c, d, e, 25); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9564 | R2(e, a, b, c, d, 26); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9565 | R2(d, e, a, b, c, 27); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9566 | R2(c, d, e, a, b, 28); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9567 | R2(b, c, d, e, a, 29); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9568 | R2(a, b, c, d, e, 30); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9569 | R2(e, a, b, c, d, 31); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9570 | R2(d, e, a, b, c, 32); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9571 | R2(c, d, e, a, b, 33); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9572 | R2(b, c, d, e, a, 34); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9573 | R2(a, b, c, d, e, 35); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9574 | R2(e, a, b, c, d, 36); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9575 | R2(d, e, a, b, c, 37); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9576 | R2(c, d, e, a, b, 38); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9577 | R2(b, c, d, e, a, 39); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9578 | R3(a, b, c, d, e, 40); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9579 | R3(e, a, b, c, d, 41); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9580 | R3(d, e, a, b, c, 42); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9581 | R3(c, d, e, a, b, 43); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9582 | R3(b, c, d, e, a, 44); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9583 | R3(a, b, c, d, e, 45); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9584 | R3(e, a, b, c, d, 46); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9585 | R3(d, e, a, b, c, 47); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9586 | R3(c, d, e, a, b, 48); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9587 | R3(b, c, d, e, a, 49); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9588 | R3(a, b, c, d, e, 50); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9589 | R3(e, a, b, c, d, 51); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9590 | R3(d, e, a, b, c, 52); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9591 | R3(c, d, e, a, b, 53); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9592 | R3(b, c, d, e, a, 54); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9593 | R3(a, b, c, d, e, 55); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9594 | R3(e, a, b, c, d, 56); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9595 | R3(d, e, a, b, c, 57); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9596 | R3(c, d, e, a, b, 58); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9597 | R3(b, c, d, e, a, 59); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9598 | R4(a, b, c, d, e, 60); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9599 | R4(e, a, b, c, d, 61); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9600 | R4(d, e, a, b, c, 62); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9601 | R4(c, d, e, a, b, 63); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9602 | R4(b, c, d, e, a, 64); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9603 | R4(a, b, c, d, e, 65); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9604 | R4(e, a, b, c, d, 66); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9605 | R4(d, e, a, b, c, 67); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9606 | R4(c, d, e, a, b, 68); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9607 | R4(b, c, d, e, a, 69); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9608 | R4(a, b, c, d, e, 70); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9609 | R4(e, a, b, c, d, 71); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9610 | R4(d, e, a, b, c, 72); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9611 | R4(c, d, e, a, b, 73); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9612 | R4(b, c, d, e, a, 74); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9613 | R4(a, b, c, d, e, 75); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9614 | R4(e, a, b, c, d, 76); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9615 | R4(d, e, a, b, c, 77); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9616 | R4(c, d, e, a, b, 78); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9617 | R4(b, c, d, e, a, 79); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9618 | state[0] += a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9619 | state[1] += b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9620 | state[2] += c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9621 | state[3] += d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9622 | state[4] += e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9623 | /* Erase working structures. The order of operations is important, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9624 | * used to ensure that compiler doesn't optimize those out. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9625 | memset(block, 0, sizeof(block)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9626 | a = b = c = d = e = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9627 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9628 | (void) b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9629 | (void) c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9630 | (void) d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9631 | (void) e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9634 | void cs_sha1_init(cs_sha1_ctx *context) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9635 | context->state[0] = 0x67452301; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9636 | context->state[1] = 0xEFCDAB89; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9637 | context->state[2] = 0x98BADCFE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9638 | context->state[3] = 0x10325476; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9639 | context->state[4] = 0xC3D2E1F0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9640 | context->count[0] = context->count[1] = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9643 | void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9644 | uint32_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9645 | uint32_t i, j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9646 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9647 | j = context->count[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9648 | if ((context->count[0] += len << 3) < j) context->count[1]++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9649 | context->count[1] += (len >> 29); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9650 | j = (j >> 3) & 63; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9651 | if ((j + len) > 63) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9652 | memcpy(&context->buffer[j], data, (i = 64 - j)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9653 | cs_sha1_transform(context->state, context->buffer); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9654 | for (; i + 63 < len; i += 64) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9655 | cs_sha1_transform(context->state, &data[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9656 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9657 | j = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9658 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 9659 | i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9660 | memcpy(&context->buffer[j], &data[i], len - i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9661 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9663 | void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9664 | unsigned i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9665 | unsigned char finalcount[8], c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9667 | for (i = 0; i < 8; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9668 | finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9669 | ((3 - (i & 3)) * 8)) & |
Marko Mikulicic |
0:c0ecb8bf28eb | 9670 | 255); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9671 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9672 | c = 0200; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9673 | cs_sha1_update(context, &c, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9674 | while ((context->count[0] & 504) != 448) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9675 | c = 0000; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9676 | cs_sha1_update(context, &c, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9678 | cs_sha1_update(context, finalcount, 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9679 | for (i = 0; i < 20; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9680 | digest[i] = |
Marko Mikulicic |
0:c0ecb8bf28eb | 9681 | (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9682 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9683 | memset(context, '\0', sizeof(*context)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9684 | memset(&finalcount, '\0', sizeof(finalcount)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9685 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9687 | void cs_hmac_sha1(const unsigned char *key, size_t keylen, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9688 | const unsigned char *data, size_t datalen, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9689 | unsigned char out[20]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9690 | cs_sha1_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9691 | unsigned char buf1[64], buf2[64], tmp_key[20], i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9693 | if (keylen > sizeof(buf1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9694 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9695 | cs_sha1_update(&ctx, key, keylen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9696 | cs_sha1_final(tmp_key, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9697 | key = tmp_key; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9698 | keylen = sizeof(tmp_key); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9701 | memset(buf1, 0, sizeof(buf1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9702 | memset(buf2, 0, sizeof(buf2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9703 | memcpy(buf1, key, keylen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9704 | memcpy(buf2, key, keylen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9706 | for (i = 0; i < sizeof(buf1); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9707 | buf1[i] ^= 0x36; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9708 | buf2[i] ^= 0x5c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9709 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9711 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9712 | cs_sha1_update(&ctx, buf1, sizeof(buf1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9713 | cs_sha1_update(&ctx, data, datalen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9714 | cs_sha1_final(out, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9716 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9717 | cs_sha1_update(&ctx, buf2, sizeof(buf2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9718 | cs_sha1_update(&ctx, out, 20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9719 | cs_sha1_final(out, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9720 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9722 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9723 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9724 | #line 1 "common/cs_dirent.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9725 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9726 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9727 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 9728 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 9729 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9730 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9731 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 9732 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9733 | /* Amalgamated: #include "common/cs_dirent.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9735 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9736 | * This file contains POSIX opendir/closedir/readdir API implementation |
Marko Mikulicic |
0:c0ecb8bf28eb | 9737 | * for systems which do not natively support it (e.g. Windows). |
Marko Mikulicic |
0:c0ecb8bf28eb | 9738 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9739 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9740 | #ifndef MG_FREE |
Marko Mikulicic |
0:c0ecb8bf28eb | 9741 | #define MG_FREE free |
Marko Mikulicic |
0:c0ecb8bf28eb | 9742 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9743 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9744 | #ifndef MG_MALLOC |
Marko Mikulicic |
0:c0ecb8bf28eb | 9745 | #define MG_MALLOC malloc |
Marko Mikulicic |
0:c0ecb8bf28eb | 9746 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9748 | #ifdef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9749 | DIR *opendir(const char *name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9750 | DIR *dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9751 | wchar_t wpath[MAX_PATH]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9752 | DWORD attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9754 | if (name == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9755 | SetLastError(ERROR_BAD_ARGUMENTS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9756 | } else if ((dir = (DIR *) MG_MALLOC(sizeof(*dir))) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9757 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9758 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9759 | to_wchar(name, wpath, ARRAY_SIZE(wpath)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9760 | attrs = GetFileAttributesW(wpath); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9761 | if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9762 | (void) wcscat(wpath, L"\\*"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9763 | dir->handle = FindFirstFileW(wpath, &dir->info); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9764 | dir->result.d_name[0] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9765 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9766 | MG_FREE(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9767 | dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9768 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9769 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9770 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9771 | return dir; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9772 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9773 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9774 | int closedir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9775 | int result = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9777 | if (dir != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9778 | if (dir->handle != INVALID_HANDLE_VALUE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 9779 | result = FindClose(dir->handle) ? 0 : -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9780 | MG_FREE(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9781 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9782 | result = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9783 | SetLastError(ERROR_BAD_ARGUMENTS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9784 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9786 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9787 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9789 | struct dirent *readdir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9790 | struct dirent *result = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9792 | if (dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9793 | if (dir->handle != INVALID_HANDLE_VALUE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9794 | result = &dir->result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9795 | (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9796 | result->d_name, sizeof(result->d_name), NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 9797 | NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9799 | if (!FindNextFileW(dir->handle, &dir->info)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9800 | (void) FindClose(dir->handle); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9801 | dir->handle = INVALID_HANDLE_VALUE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9804 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9805 | SetLastError(ERROR_FILE_NOT_FOUND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9806 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9807 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9808 | SetLastError(ERROR_BAD_ARGUMENTS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9809 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9811 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9812 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9813 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9815 | #ifdef CS_ENABLE_SPIFFS |
Marko Mikulicic |
0:c0ecb8bf28eb | 9816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9817 | DIR *opendir(const char *dir_name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9818 | DIR *dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9819 | extern spiffs fs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9821 | if (dir_name != NULL && (dir = (DIR *) malloc(sizeof(*dir))) != NULL && |
Marko Mikulicic |
0:c0ecb8bf28eb | 9822 | SPIFFS_opendir(&fs, (char *) dir_name, &dir->dh) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9823 | free(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9824 | dir = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9825 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9827 | return dir; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9828 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9830 | int closedir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9831 | if (dir != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9832 | SPIFFS_closedir(&dir->dh); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9833 | free(dir); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9834 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9835 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9836 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9837 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9838 | struct dirent *readdir(DIR *dir) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9839 | return SPIFFS_readdir(&dir->dh, &dir->de); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9840 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9842 | /* SPIFFs doesn't support directory operations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9843 | int rmdir(const char *path) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9844 | (void) path; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9845 | return ENOTDIR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9848 | int mkdir(const char *path, mode_t mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9849 | (void) path; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9850 | (void) mode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9851 | /* for spiffs supports only root dir, which comes from mongoose as '.' */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9852 | return (strlen(path) == 1 && *path == '.') ? 0 : ENOTDIR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9853 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9855 | #endif /* CS_ENABLE_SPIFFS */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9856 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9857 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9859 | /* ISO C requires a translation unit to contain at least one declaration */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9860 | typedef int cs_dirent_dummy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9861 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9862 | #line 1 "common/cs_file.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9863 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9864 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9865 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 9866 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 9867 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9869 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9871 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9872 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9874 | #ifdef CS_MMAP |
Marko Mikulicic |
0:c0ecb8bf28eb | 9875 | #include <fcntl.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9876 | #include <sys/mman.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9877 | #include <sys/stat.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9878 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9880 | #ifndef EXCLUDE_COMMON |
Marko Mikulicic |
0:c0ecb8bf28eb | 9881 | char *cs_read_file(const char *path, size_t *size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9882 | FILE *fp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9883 | char *data = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9884 | if ((fp = fopen(path, "rb")) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9885 | } else if (fseek(fp, 0, SEEK_END) != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9886 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9887 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9888 | *size = ftell(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9889 | data = (char *) malloc(*size + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9890 | if (data != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9891 | fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9892 | if (fread(data, 1, *size, fp) != *size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9893 | free(data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9894 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9895 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9896 | data[*size] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9897 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9898 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9899 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9900 | return data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9901 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9902 | #endif /* EXCLUDE_COMMON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9904 | #ifdef CS_MMAP |
Marko Mikulicic |
0:c0ecb8bf28eb | 9905 | char *cs_mmap_file(const char *path, size_t *size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9906 | char *r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9907 | int fd = open(path, O_RDONLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9908 | struct stat st; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9909 | if (fd == -1) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9910 | fstat(fd, &st); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9911 | *size = (size_t) st.st_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9912 | r = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9913 | if (r == MAP_FAILED) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9914 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9916 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9917 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 9918 | #line 1 "common/cs_strtod.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 9919 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 9920 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9921 | #include <math.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9923 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 9924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9925 | int cs_strncasecmp(const char *s1, const char *s2, size_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9926 | if (n == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9927 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9928 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9930 | while (n-- != 0 && tolower((int) *s1) == tolower((int) *s2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9931 | if (n == 0 || *s1 == '\0' || *s2 == '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9932 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9933 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9934 | s1++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9935 | s2++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9936 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9937 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9938 | return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9939 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9941 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 9942 | * based on Source: |
Marko Mikulicic |
0:c0ecb8bf28eb | 9943 | * https://github.com/anakod/Sming/blob/master/Sming/system/stringconversion.cpp#L93 |
Marko Mikulicic |
0:c0ecb8bf28eb | 9944 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9946 | double cs_strtod(const char *str, char **endptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9947 | double result = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9948 | char c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9949 | const char *str_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9950 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9951 | unsigned neg : 1; /* result is negative */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9952 | unsigned decimals : 1; /* parsing decimal part */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9953 | unsigned is_exp : 1; /* parsing exponent like e+5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9954 | unsigned is_exp_neg : 1; /* exponent is negative */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9955 | } flags = {0, 0, 0, 0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9956 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9957 | while (isspace((int) *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9958 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9959 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9961 | if (*str == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9962 | /* only space in str? */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9963 | if (endptr != 0) *endptr = (char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9964 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9965 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9967 | /* Handle leading plus/minus signs */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9968 | while (*str == '-' || *str == '+') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9969 | if (*str == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9970 | flags.neg = !flags.neg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9971 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9972 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9973 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9975 | if (cs_strncasecmp(str, "NaN", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9976 | if (endptr != 0) *endptr = (char *) str + 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9977 | return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9978 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9980 | if (cs_strncasecmp(str, "INF", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9981 | str += 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9982 | if (cs_strncasecmp(str, "INITY", 5) == 0) str += 5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9983 | if (endptr != 0) *endptr = (char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9984 | return flags.neg ? -INFINITY : INFINITY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9985 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 9986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9987 | str_start = str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 9989 | if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9990 | /* base 16 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 9991 | str += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9992 | while ((c = tolower((int) *str))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9993 | int d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9994 | if (c >= '0' && c <= '9') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9995 | d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 9996 | } else if (c >= 'a' && c <= 'f') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9997 | d = 10 + (c - 'a'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 9998 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 9999 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10001 | result = 16 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10002 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10003 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10004 | } else if (*str == '0' && (*(str + 1) == 'b' || *(str + 1) == 'B')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10005 | /* base 2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10006 | str += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10007 | while ((c = *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10008 | int d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10009 | if (c != '0' && c != '1') break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10010 | result = 2 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10011 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10012 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10013 | } else if (*str == '0' && *(str + 1) >= '0' && *(str + 1) <= '7') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10014 | /* base 8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10015 | while ((c = *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10016 | int d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10017 | if (c < '0' || c > '7') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10018 | /* fallback to base 10 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10019 | str = str_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10020 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10021 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10022 | result = 8 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10023 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10024 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10025 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10027 | if (str == str_start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10028 | /* base 10 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10029 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10030 | /* exponent specified explicitly, like in 3e-5, exponent is -5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10031 | int exp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10032 | /* exponent calculated from dot, like in 1.23, exponent is -2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10033 | int exp_dot = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10035 | result = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10037 | while ((c = *str)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10038 | int d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10040 | if (c == '.') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10041 | if (!flags.decimals) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10042 | /* going to parse decimal part */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10043 | flags.decimals = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10044 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10045 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10046 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10047 | /* non-expected dot: assume number data is over */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10048 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10049 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10050 | } else if (c == 'e' || c == 'E') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10051 | /* going to parse exponent part */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10052 | flags.is_exp = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10053 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10054 | c = *str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10056 | /* check sign of the exponent */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10057 | if (c == '-' || c == '+') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10058 | if (c == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10059 | flags.is_exp_neg = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10061 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10062 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10064 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10065 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10066 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10067 | d = c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10068 | if (d < 0 || d > 9) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10069 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10070 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10072 | if (!flags.is_exp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10073 | /* apply current digit to the result */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10074 | result = 10 * result + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10075 | if (flags.decimals) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10076 | exp_dot--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10078 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10079 | /* apply current digit to the exponent */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10080 | if (flags.is_exp_neg) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10081 | if (exp > -1022) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10082 | exp = 10 * exp - d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10083 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10084 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10085 | if (exp < 1023) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10086 | exp = 10 * exp + d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10087 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10089 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10091 | str++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10094 | exp += exp_dot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10095 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10096 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10097 | * TODO(dfrank): it probably makes sense not to adjust intermediate `double |
Marko Mikulicic |
0:c0ecb8bf28eb | 10098 | * result`, but build double number accordingly to IEEE 754 from taken |
Marko Mikulicic |
0:c0ecb8bf28eb | 10099 | * (integer) mantissa, exponent and sign. That would work faster, and we |
Marko Mikulicic |
0:c0ecb8bf28eb | 10100 | * can avoid any possible round errors. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10101 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10103 | /* if exponent is non-zero, apply it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10104 | if (exp != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10105 | if (exp < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10106 | while (exp++ != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10107 | result /= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10108 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10109 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10110 | while (exp-- != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10111 | result *= 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10112 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10113 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10114 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10115 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10116 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10117 | if (flags.neg) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10118 | result = -result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10121 | if (endptr != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10122 | *endptr = (char *) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10123 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10125 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10126 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10127 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10128 | #line 1 "common/coroutine.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10129 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10130 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10131 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10132 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10133 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10134 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10135 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10136 | * Module that provides generic macros and functions to implement "coroutines", |
Marko Mikulicic |
0:c0ecb8bf28eb | 10137 | * i.e. C code that uses `mbuf` as a stack for function calls. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10138 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 10139 | * More info: see the design doc: https://goo.gl/kfcG61 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10140 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10142 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10143 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10145 | /* Amalgamated: #include "common/coroutine.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10147 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10148 | * Unwinds stack by 1 function. Used when we're returning from function and |
Marko Mikulicic |
0:c0ecb8bf28eb | 10149 | * when an exception is thrown. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10150 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10151 | static void _level_up(struct cr_ctx *p_ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10152 | /* get size of current function's stack data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10153 | size_t locals_size = _CR_CURR_FUNC_LOCALS_SIZE(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10154 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10155 | /* check stacks underflow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10156 | if (_CR_STACK_FID_UND_CHECK(p_ctx, 1 /*fid*/)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10157 | p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10158 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10159 | } else if (_CR_STACK_DATA_UND_CHECK(p_ctx, locals_size)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10160 | p_ctx->status = CR_RES__ERR_STACK_DATA_UNDERFLOW; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10161 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10162 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10164 | /* decrement stacks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10165 | _CR_STACK_DATA_FREE(p_ctx, locals_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10166 | _CR_STACK_FID_FREE(p_ctx, 1 /*fid*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10167 | p_ctx->stack_ret.len = p_ctx->cur_fid_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10169 | /* if we have exception marker here, adjust cur_fid_idx */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10170 | while (CR_CURR_FUNC_C(p_ctx) == CR_FID__TRY_MARKER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10171 | /* check for stack underflow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10172 | if (_CR_STACK_FID_UND_CHECK(p_ctx, _CR_TRY_SIZE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10173 | p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10174 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10175 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10176 | _CR_STACK_FID_FREE(p_ctx, _CR_TRY_SIZE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10177 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10178 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10180 | enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10181 | if (p_ctx->status != CR_RES__OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10182 | goto out; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10183 | } else if (p_ctx->called_fid != CR_FID__NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10184 | /* need to call new function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10186 | size_t locals_size = p_ctx->p_func_descrs[p_ctx->called_fid].locals_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10187 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10188 | * increment stack pointers |
Marko Mikulicic |
0:c0ecb8bf28eb | 10189 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10190 | /* make sure this function has correct `struct cr_func_desc` entry */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10191 | assert(locals_size == p_ctx->call_locals_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10192 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10193 | * make sure we haven't mistakenly included "zero-sized" `.._arg_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 10194 | * structure in `.._locals_t` struct |
Marko Mikulicic |
0:c0ecb8bf28eb | 10195 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 10196 | * By "zero-sized" I mean `cr_zero_size_type_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10197 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10198 | assert(locals_size < sizeof(cr_zero_size_type_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10199 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10200 | _CR_STACK_DATA_ALLOC(p_ctx, locals_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10201 | _CR_STACK_RET_ALLOC(p_ctx, 1 /*fid*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10202 | p_ctx->cur_fid_idx = p_ctx->stack_ret.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10204 | /* copy arguments to our "stack" (and advance locals stack pointer) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10205 | memcpy(p_ctx->stack_data.buf + p_ctx->stack_data.len - locals_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10206 | p_ctx->p_arg_retval, p_ctx->call_arg_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10207 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10208 | /* set function id */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10209 | CR_CURR_FUNC_C(p_ctx) = p_ctx->called_fid; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10210 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10211 | /* clear called_fid */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10212 | p_ctx->called_fid = CR_FID__NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10214 | } else if (p_ctx->need_return) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10215 | /* need to return from the currently running function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10216 | |
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 | p_ctx->need_return = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10223 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10224 | } else if (p_ctx->need_yield) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10225 | /* need to yield */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10226 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10227 | p_ctx->need_yield = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10228 | p_ctx->status = CR_RES__OK_YIELDED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10229 | goto out; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10230 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10231 | } else if (p_ctx->thrown_exc != CR_EXC_ID__NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10232 | /* exception was thrown */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10233 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10234 | /* unwind stack until we reach the bottom, or find some try-catch blocks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10235 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10236 | _level_up(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10237 | if (p_ctx->status != CR_RES__OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10238 | goto out; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10239 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10240 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10241 | if (_CR_TRY_MARKER(p_ctx) == CR_FID__TRY_MARKER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10242 | /* we have some try-catch here, go to the first catch */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10243 | CR_CURR_FUNC_C(p_ctx) = _CR_TRY_CATCH_FID(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10244 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10245 | } else if (CR_CURR_FUNC_C(p_ctx) == CR_FID__NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10246 | /* we've reached the bottom of the stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10247 | p_ctx->status = CR_RES__ERR_UNCAUGHT_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10248 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10251 | } while (1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10252 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10253 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10254 | /* remember pointer to current function's locals */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10255 | _CR_CUR_FUNC_LOCALS_UPD(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10257 | out: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10258 | return p_ctx->status; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10259 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10261 | void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10262 | size_t arg_retval_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10263 | const struct cr_func_desc *p_func_descrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10264 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10265 | * make sure we haven't mistakenly included "zero-sized" `.._arg_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 10266 | * structure in `union user_arg_ret`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10267 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 10268 | * By "zero-sized" I mean `cr_zero_size_type_t`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10269 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10270 | assert(arg_retval_size < sizeof(cr_zero_size_type_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10271 | #ifdef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 10272 | (void) arg_retval_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10273 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10275 | memset(p_ctx, 0x00, sizeof(*p_ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10277 | p_ctx->p_func_descrs = p_func_descrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10278 | p_ctx->p_arg_retval = p_arg_retval; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10280 | mbuf_init(&p_ctx->stack_data, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10281 | mbuf_init(&p_ctx->stack_ret, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10283 | mbuf_append(&p_ctx->stack_ret, NULL, 1 /*starting byte for CR_FID__NONE*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10284 | p_ctx->cur_fid_idx = p_ctx->stack_ret.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10286 | _CR_CALL_PREPARE(p_ctx, CR_FID__NONE, 0, 0, CR_FID__NONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10287 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10289 | void cr_context_free(struct cr_ctx *p_ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10290 | mbuf_free(&p_ctx->stack_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10291 | mbuf_free(&p_ctx->stack_ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10292 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10293 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
1:887cf63a2a0b | 10294 | #line 1 "common/platforms/mbed/mbed_libc.c" |
Marko Mikulicic |
1:887cf63a2a0b | 10295 | #endif |
Marko Mikulicic |
1:887cf63a2a0b | 10296 | /* |
Marko Mikulicic |
1:887cf63a2a0b | 10297 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
1:887cf63a2a0b | 10298 | * All rights reserved |
Marko Mikulicic |
1:887cf63a2a0b | 10299 | */ |
Marko Mikulicic |
1:887cf63a2a0b | 10300 | |
Marko Mikulicic |
1:887cf63a2a0b | 10301 | #if CS_PLATFORM == CS_P_MBED |
Marko Mikulicic |
1:887cf63a2a0b | 10302 | |
Marko Mikulicic |
1:887cf63a2a0b | 10303 | long timezone; |
Marko Mikulicic |
1:887cf63a2a0b | 10304 | |
Marko Mikulicic |
1:887cf63a2a0b | 10305 | #endif /* CS_PLATFORM == CS_P_MBED */ |
Marko Mikulicic |
1:887cf63a2a0b | 10306 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10307 | #line 1 "v7/builtin/file.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10308 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10309 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10310 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10311 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10312 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10314 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10315 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10316 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10317 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10318 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10319 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10320 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10321 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10322 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10323 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10324 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10325 | /* Amalgamated: #include "common/cs_dirent.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10327 | #if defined(V7_ENABLE_FILE) && !defined(V7_NO_FS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 10328 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10329 | static const char s_fd_prop[] = "__fd"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10331 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 10332 | static FILE *v7_val_to_file(struct v7 *v7, v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10333 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10334 | return (FILE *) v7_get_ptr(v7, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10335 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10337 | static v7_val_t v7_file_to_val(struct v7 *v7, FILE *file) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10338 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10339 | return v7_mk_foreign(v7, file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10340 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10342 | static int v7_is_file_type(v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10343 | return v7_is_foreign(val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10345 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10346 | FILE *v7_val_to_file(struct v7 *v7, v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10347 | v7_val_t v7_file_to_val(struct v7 *v7, FILE *file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10348 | int v7_is_file_type(v7_val_t val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10349 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10351 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10352 | V7_PRIVATE enum v7_err File_eval(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10353 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10354 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10356 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10358 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10359 | const char *s = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10360 | if (s == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10361 | rcode = v7_throwf(v7, "TypeError", "Invalid string"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10362 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10365 | v7_set_gc_enabled(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10366 | rcode = v7_exec_file(v7, s, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10367 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10368 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10370 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10371 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10372 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10373 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10374 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10376 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10377 | V7_PRIVATE enum v7_err File_exists(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10378 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10379 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10381 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10383 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10384 | const char *fname = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10385 | if (fname != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10386 | struct stat st; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10387 | if (stat(fname, &st) == 0) *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10389 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10391 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10392 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10394 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10395 | static enum v7_err f_read(struct v7 *v7, int all, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10396 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10397 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10398 | v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10400 | if (v7_is_file_type(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10401 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10402 | char buf[BUFSIZ]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10403 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10404 | FILE *fp = v7_val_to_file(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10406 | /* Read file contents into mbuf */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10407 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10408 | while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10409 | mbuf_append(&m, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10410 | if (!all) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10411 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10412 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10413 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10415 | if (m.len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10416 | *res = v7_mk_string(v7, m.buf, m.len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10417 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10418 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10419 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10420 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10421 | *res = v7_mk_string(v7, "", 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10422 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10423 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10424 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10425 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10427 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10428 | V7_PRIVATE enum v7_err File_obj_read(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10429 | return f_read(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10430 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10432 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10433 | V7_PRIVATE enum v7_err File_obj_write(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10434 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10435 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10436 | v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10437 | v7_val_t arg1 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10438 | size_t n, sent = 0, len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10440 | if (v7_is_file_type(arg0) && v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10441 | const char *s = v7_get_string(v7, &arg1, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10442 | FILE *fp = v7_val_to_file(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10443 | while (sent < len && (n = fwrite(s + sent, 1, len - sent, fp)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10444 | sent += n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10445 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10448 | *res = v7_mk_number(v7, sent); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10450 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10451 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10453 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10454 | V7_PRIVATE enum v7_err File_obj_close(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10455 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10456 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10457 | v7_val_t prop = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10458 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10460 | if (v7_is_file_type(prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10461 | ires = fclose(v7_val_to_file(v7, prop)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10462 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10464 | *res = v7_mk_number(v7, ires); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10466 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10467 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10469 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10470 | V7_PRIVATE enum v7_err File_open(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10471 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10472 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10473 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10474 | FILE *fp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10475 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10476 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10477 | const char *s1 = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10478 | const char *s2 = "rb"; /* Open files in read mode by default */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10480 | if (v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10481 | s2 = v7_get_cstring(v7, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10482 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10484 | if (s1 == NULL || s2 == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10485 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10486 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10489 | fp = fopen(s1, s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10490 | if (fp != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10491 | v7_val_t obj = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10492 | v7_val_t file_proto = v7_get( |
Marko Mikulicic |
0:c0ecb8bf28eb | 10493 | v7, v7_get(v7, v7_get_global(v7), "File", ~0), "prototype", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10494 | v7_set_proto(v7, obj, file_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10495 | v7_def(v7, obj, s_fd_prop, sizeof(s_fd_prop) - 1, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 10496 | v7_file_to_val(v7, fp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10497 | *res = obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10498 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10499 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10500 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10502 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10503 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10504 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10505 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10506 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10508 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10509 | V7_PRIVATE enum v7_err File_read(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10510 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10512 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10513 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10514 | size_t size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10515 | char *data = cs_read_file(path, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10516 | if (data != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10517 | *res = v7_mk_string(v7, data, size, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10518 | free(data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10519 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10520 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10521 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10522 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10525 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10526 | V7_PRIVATE enum v7_err File_write(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10527 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10528 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10529 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10531 | if (v7_is_string(arg0) && v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10532 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10533 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10534 | const char *buf = v7_get_string(v7, &arg1, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10535 | FILE *fp = fopen(path, "wb+"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10536 | if (fp != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10537 | if (fwrite(buf, 1, len, fp) == len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10538 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10539 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10540 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10541 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10544 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10545 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10546 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10547 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10548 | V7_PRIVATE enum v7_err File_rename(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10549 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10550 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10551 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10552 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10553 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10554 | if (v7_is_string(arg0) && v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10555 | const char *from = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10556 | const char *to = v7_get_cstring(v7, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10557 | if (from == NULL || to == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10558 | *res = v7_mk_number(v7, ENOENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10559 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10560 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10562 | ires = rename(from, to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10563 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10565 | *res = v7_mk_number(v7, ires == 0 ? 0 : errno); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10567 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10568 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10569 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10571 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10572 | V7_PRIVATE enum v7_err File_loadJSON(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10573 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10574 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10576 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10578 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10579 | const char *file_name = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10580 | if (file_name == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10581 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10582 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10584 | rcode = v7_parse_json_file(v7, file_name, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10585 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10586 | /* swallow exception and return undefined */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10587 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10588 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10589 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10590 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10593 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10594 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10597 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10598 | V7_PRIVATE enum v7_err File_remove(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10599 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10600 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10601 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10603 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10604 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10605 | if (path == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10606 | *res = v7_mk_number(v7, ENOENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10607 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10608 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10609 | ires = remove(path); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10610 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10611 | *res = v7_mk_number(v7, ires == 0 ? 0 : errno); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10612 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10613 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10614 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10615 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10616 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10617 | #if V7_ENABLE__File__list |
Marko Mikulicic |
0:c0ecb8bf28eb | 10618 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10619 | V7_PRIVATE enum v7_err File_list(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10620 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10621 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10623 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10624 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10625 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10626 | const char *path = v7_get_cstring(v7, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10627 | struct dirent *dp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10628 | DIR *dirp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10630 | if (path == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10631 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10634 | if ((dirp = (opendir(path))) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10635 | *res = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10636 | while ((dp = readdir(dirp)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10637 | /* Do not show current and parent dirs */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10638 | if (strcmp((const char *) dp->d_name, ".") == 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 10639 | strcmp((const char *) dp->d_name, "..") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10640 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10642 | /* Add file name to the list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10643 | v7_array_push(v7, *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10644 | v7_mk_string(v7, (const char *) dp->d_name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10645 | strlen((const char *) dp->d_name), 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10646 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10647 | closedir(dirp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10648 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10649 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10651 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10652 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10653 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10654 | #endif /* V7_ENABLE__File__list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10656 | void init_file(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10657 | v7_val_t file_obj = v7_mk_object(v7), file_proto = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10658 | v7_set(v7, v7_get_global(v7), "File", 4, file_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10659 | v7_set(v7, file_obj, "prototype", 9, file_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10661 | v7_set_method(v7, file_obj, "eval", File_eval); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10662 | v7_set_method(v7, file_obj, "exists", File_exists); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10663 | v7_set_method(v7, file_obj, "remove", File_remove); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10664 | v7_set_method(v7, file_obj, "rename", File_rename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10665 | v7_set_method(v7, file_obj, "open", File_open); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10666 | v7_set_method(v7, file_obj, "read", File_read); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10667 | v7_set_method(v7, file_obj, "write", File_write); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10668 | v7_set_method(v7, file_obj, "loadJSON", File_loadJSON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10669 | #if V7_ENABLE__File__list |
Marko Mikulicic |
0:c0ecb8bf28eb | 10670 | v7_set_method(v7, file_obj, "list", File_list); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10671 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10673 | v7_set_method(v7, file_proto, "close", File_obj_close); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10674 | v7_set_method(v7, file_proto, "read", File_obj_read); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10675 | v7_set_method(v7, file_proto, "write", File_obj_write); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10676 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10677 | #if V7_ENABLE__File__require |
Marko Mikulicic |
0:c0ecb8bf28eb | 10678 | v7_def(v7, v7_get_global(v7), "_modcache", ~0, 0, v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10679 | if (v7_exec(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10680 | "function require(m) { " |
Marko Mikulicic |
0:c0ecb8bf28eb | 10681 | " if (m in _modcache) { return _modcache[m]; }" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10682 | " var module = {exports:{}};" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10683 | " File.eval(m);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10684 | " return (_modcache[m] = module.exports)" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10685 | " }", |
Marko Mikulicic |
0:c0ecb8bf28eb | 10686 | NULL) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10687 | /* TODO(mkm): percolate failure */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10688 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10689 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10690 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10691 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10692 | void init_file(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10693 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10694 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10695 | #endif /* NO_LIBC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10696 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10697 | #line 1 "v7/builtin/socket.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10698 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10699 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10700 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10701 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10702 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10704 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10705 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10706 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10707 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10708 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10709 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10710 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10711 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10713 | #ifdef V7_ENABLE_SOCKET |
Marko Mikulicic |
0:c0ecb8bf28eb | 10714 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10715 | #ifdef __WATCOM__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10716 | #define SOMAXCONN 128 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10717 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10719 | #ifndef RECV_BUF_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 10720 | #define RECV_BUF_SIZE 1024 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10721 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10723 | static const char s_sock_prop[] = "__sock"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10725 | static uint32_t s_resolve(struct v7 *v7, v7_val_t ip_address) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10726 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10727 | const char *s = v7_get_string(v7, &ip_address, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10728 | struct hostent *he = gethostbyname(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10729 | return he == NULL ? 0 : *(uint32_t *) he->h_addr_list[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10732 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10733 | static enum v7_err s_fd_to_sock_obj(struct v7 *v7, sock_t fd, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10734 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10735 | v7_val_t sock_proto = |
Marko Mikulicic |
0:c0ecb8bf28eb | 10736 | v7_get(v7, v7_get(v7, v7_get_global(v7), "Socket", ~0), "prototype", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10737 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10738 | *res = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10739 | v7_set_proto(v7, *res, sock_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10740 | v7_def(v7, *res, s_sock_prop, sizeof(s_sock_prop) - 1, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 10741 | v7_mk_number(v7, fd)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10743 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10744 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10746 | /* Socket.connect(host, port [, is_udp]) -> socket_object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10747 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10748 | V7_PRIVATE enum v7_err Socket_connect(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10749 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10750 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10751 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10752 | v7_val_t arg2 = v7_arg(v7, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10754 | if (v7_is_number(arg1) && v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10755 | struct sockaddr_in sin; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10756 | sock_t sock = |
Marko Mikulicic |
0:c0ecb8bf28eb | 10757 | socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10758 | memset(&sin, 0, sizeof(sin)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10759 | sin.sin_family = AF_INET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10760 | sin.sin_addr.s_addr = s_resolve(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10761 | sin.sin_port = htons((uint16_t) v7_get_double(v7, arg1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10762 | if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10763 | closesocket(sock); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10764 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10765 | rcode = s_fd_to_sock_obj(v7, sock, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10766 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10767 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10768 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10770 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10771 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10772 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10773 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10774 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10775 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10776 | /* Socket.listen(port [, ip_address [,is_udp]]) -> sock */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10777 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10778 | V7_PRIVATE enum v7_err Socket_listen(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10779 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10780 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10781 | v7_val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10782 | v7_val_t arg2 = v7_arg(v7, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10784 | if (v7_is_number(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10785 | struct sockaddr_in sin; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10786 | int on = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10787 | sock_t sock = |
Marko Mikulicic |
0:c0ecb8bf28eb | 10788 | socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10789 | memset(&sin, 0, sizeof(sin)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10790 | sin.sin_family = AF_INET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10791 | sin.sin_port = htons((uint16_t) v7_get_double(v7, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10792 | if (v7_is_string(arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10793 | sin.sin_addr.s_addr = s_resolve(v7, arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10794 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10796 | #if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 10797 | /* "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" http://goo.gl/RmrFTm */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10798 | setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &on, sizeof(on)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10799 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10800 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10801 | #if !defined(_WIN32) || defined(SO_EXCLUSIVEADDRUSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 10802 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10803 | * SO_RESUSEADDR is not enabled on Windows because the semantics of |
Marko Mikulicic |
0:c0ecb8bf28eb | 10804 | * SO_REUSEADDR on UNIX and Windows is different. On Windows, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10805 | * SO_REUSEADDR allows to bind a socket to a port without error even if |
Marko Mikulicic |
0:c0ecb8bf28eb | 10806 | * the port is already open by another program. This is not the behavior |
Marko Mikulicic |
0:c0ecb8bf28eb | 10807 | * SO_REUSEADDR was designed for, and leads to hard-to-track failure |
Marko Mikulicic |
0:c0ecb8bf28eb | 10808 | * scenarios. Therefore, SO_REUSEADDR was disabled on Windows unless |
Marko Mikulicic |
0:c0ecb8bf28eb | 10809 | * SO_EXCLUSIVEADDRUSE is supported and set on a socket. |
Marko Mikulicic |
0:c0ecb8bf28eb | 10810 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10811 | setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10812 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10813 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10814 | if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10815 | listen(sock, SOMAXCONN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10816 | rcode = s_fd_to_sock_obj(v7, sock, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10817 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10818 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10819 | closesocket(sock); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10820 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10823 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10824 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10825 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10826 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10829 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10830 | V7_PRIVATE enum v7_err Socket_accept(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10831 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10832 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10833 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10835 | if (v7_is_number(prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10836 | struct sockaddr_in sin; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10837 | socklen_t len = sizeof(sin); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10838 | sock_t sock = (sock_t) v7_get_double(v7, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10839 | sock_t fd = accept(sock, (struct sockaddr *) &sin, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10840 | if (fd != INVALID_SOCKET) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10841 | rcode = s_fd_to_sock_obj(v7, fd, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10842 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10843 | char *remote_host = inet_ntoa(sin.sin_addr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10844 | v7_set(v7, *res, "remoteHost", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10845 | v7_mk_string(v7, remote_host, ~0, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10847 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10848 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10849 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10850 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10852 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10853 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10854 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10855 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10856 | /* sock.close() -> errno */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10857 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10858 | V7_PRIVATE enum v7_err Socket_close(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10859 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10860 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10861 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10862 | *res = v7_mk_number(v7, closesocket((sock_t) v7_get_double(v7, prop))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10863 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10864 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10867 | /* sock.recv() -> string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10868 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10869 | static enum v7_err s_recv(struct v7 *v7, int all, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10870 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10871 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10872 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10874 | if (v7_is_number(prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10875 | char buf[RECV_BUF_SIZE]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10876 | sock_t sock = (sock_t) v7_get_double(v7, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10877 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10878 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10880 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10881 | while ((n = recv(sock, buf, sizeof(buf), 0)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10882 | mbuf_append(&m, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10883 | if (!all) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10884 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10885 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10888 | if (n <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10889 | closesocket(sock); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10890 | v7_def(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10891 | V7_DESC_ENUMERABLE(0), v7_mk_number(v7, INVALID_SOCKET)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10892 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10894 | if (m.len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10895 | *res = v7_mk_string(v7, m.buf, m.len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10896 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10897 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10898 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10899 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10901 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10903 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 10904 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10907 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10908 | V7_PRIVATE enum v7_err Socket_recvAll(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10909 | return s_recv(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10912 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10913 | V7_PRIVATE enum v7_err Socket_recv(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10914 | return s_recv(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10917 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10918 | V7_PRIVATE enum v7_err Socket_send(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10919 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10920 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10921 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10922 | v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10923 | size_t len, sent = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10925 | if (v7_is_number(prop) && v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10926 | const char *s = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10927 | sock_t sock = (sock_t) v7_get_double(v7, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10928 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10930 | while (sent < len && (n = send(sock, s + sent, len - sent, 0)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10931 | sent += n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10932 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10933 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10935 | *res = v7_mk_number(v7, sent); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10937 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10938 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10940 | void init_socket(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10941 | v7_val_t socket_obj = v7_mk_object(v7), sock_proto = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10943 | v7_set(v7, v7_get_global(v7), "Socket", 6, socket_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10944 | sock_proto = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10945 | v7_set(v7, socket_obj, "prototype", 9, sock_proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10946 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10947 | v7_set_method(v7, socket_obj, "connect", Socket_connect); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10948 | v7_set_method(v7, socket_obj, "listen", Socket_listen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10950 | v7_set_method(v7, sock_proto, "accept", Socket_accept); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10951 | v7_set_method(v7, sock_proto, "send", Socket_send); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10952 | v7_set_method(v7, sock_proto, "recv", Socket_recv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10953 | v7_set_method(v7, sock_proto, "recvAll", Socket_recvAll); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10954 | v7_set_method(v7, sock_proto, "close", Socket_close); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10956 | #ifdef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 10957 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10958 | WSADATA data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10959 | WSAStartup(MAKEWORD(2, 2), &data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10960 | /* TODO(alashkin): add WSACleanup call */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10961 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10962 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10963 | signal(SIGPIPE, SIG_IGN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10964 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10965 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10966 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 10967 | void init_socket(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10968 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 10970 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10971 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 10972 | #line 1 "v7/builtin/crypto.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 10973 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 10974 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 10975 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 10976 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 10977 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10979 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10980 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 10981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10982 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10983 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10984 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10985 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10986 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10987 | /* Amalgamated: #include "common/md5.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10988 | /* Amalgamated: #include "common/sha1.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10989 | /* Amalgamated: #include "common/base64.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 10990 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10991 | #ifdef V7_ENABLE_CRYPTO |
Marko Mikulicic |
0:c0ecb8bf28eb | 10992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10993 | typedef void (*b64_func_t)(const unsigned char *, int, char *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 10994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 10995 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 10996 | static enum v7_err b64_transform(struct v7 *v7, b64_func_t func, double mult, |
Marko Mikulicic |
0:c0ecb8bf28eb | 10997 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 10998 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 10999 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11000 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11002 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11003 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11004 | const char *s = v7_get_string(v7, &arg0, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11005 | char *buf = (char *) malloc(n * mult + 4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11006 | if (buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11007 | func((const unsigned char *) s, (int) n, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11008 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11009 | free(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11010 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11011 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11013 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11014 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11015 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11016 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11017 | V7_PRIVATE enum v7_err Crypto_base64_decode(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11018 | return b64_transform(v7, (b64_func_t) cs_base64_decode, 0.75, res); |
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_base64_encode(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11023 | return b64_transform(v7, cs_base64_encode, 1.5, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11024 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11026 | static void v7_md5(const char *data, size_t len, char buf[16]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11027 | MD5_CTX ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11028 | MD5_Init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11029 | MD5_Update(&ctx, (unsigned char *) data, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11030 | MD5_Final((unsigned char *) buf, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11031 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11033 | static void v7_sha1(const char *data, size_t len, char buf[20]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11034 | cs_sha1_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11035 | cs_sha1_init(&ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11036 | cs_sha1_update(&ctx, (unsigned char *) data, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11037 | cs_sha1_final((unsigned char *) buf, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11038 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11040 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11041 | V7_PRIVATE enum v7_err Crypto_md5(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11042 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11043 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11045 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11046 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11047 | const char *data = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11048 | char buf[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11049 | v7_md5(data, len, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11050 | *res = v7_mk_string(v7, buf, sizeof(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11051 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11052 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11054 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11056 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11057 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11060 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11061 | V7_PRIVATE enum v7_err Crypto_md5_hex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11062 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11063 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11065 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11066 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11067 | const char *data = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11068 | char hash[16], buf[sizeof(hash) * 2 + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11069 | v7_md5(data, len, hash); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11070 | cs_to_hex(buf, (unsigned char *) hash, sizeof(hash)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11071 | *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 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(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 buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11089 | v7_sha1(data, len, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11090 | *res = v7_mk_string(v7, buf, sizeof(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11091 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11093 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11095 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11096 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11097 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11098 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11099 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11100 | V7_PRIVATE enum v7_err Crypto_sha1_hex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11101 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11102 | v7_val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11104 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11105 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11106 | const char *data = v7_get_string(v7, &arg0, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11107 | char hash[20], buf[sizeof(hash) * 2 + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11108 | v7_sha1(data, len, hash); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11109 | cs_to_hex(buf, (unsigned char *) hash, sizeof(hash)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11110 | *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11111 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11112 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11113 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11115 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11116 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11117 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11118 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11119 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11120 | void init_crypto(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11121 | #ifdef V7_ENABLE_CRYPTO |
Marko Mikulicic |
0:c0ecb8bf28eb | 11122 | v7_val_t obj = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11123 | v7_set(v7, v7_get_global(v7), "Crypto", 6, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11124 | v7_set_method(v7, obj, "md5", Crypto_md5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11125 | v7_set_method(v7, obj, "md5_hex", Crypto_md5_hex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11126 | v7_set_method(v7, obj, "sha1", Crypto_sha1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11127 | v7_set_method(v7, obj, "sha1_hex", Crypto_sha1_hex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11128 | v7_set_method(v7, obj, "base64_encode", Crypto_base64_encode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11129 | v7_set_method(v7, obj, "base64_decode", Crypto_base64_decode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11130 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 11131 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11132 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11133 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11134 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11135 | #line 1 "v7/src/varint.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11136 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11137 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11138 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 11139 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 11140 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11141 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11142 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11143 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11145 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11146 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11147 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11148 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11149 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11150 | * Strings in AST are encoded as tuples (length, string). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11151 | * Length is variable-length: if high bit is set in a byte, next byte is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11152 | * Maximum string length with such encoding is 2 ^ (7 * 4) == 256 MiB, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11153 | * assuming that sizeof(size_t) == 4. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11154 | * Small string length (less then 128 bytes) is encoded in 1 byte. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11155 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11156 | V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11157 | size_t i = 0, string_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11159 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11160 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11161 | * Each byte of varint contains 7 bits, in little endian order. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11162 | * MSB is a continuation bit: it tells whether next byte is used. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11163 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11164 | string_len |= (p[i] & 0x7f) << (7 * i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11165 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11166 | * First we increment i, then check whether it is within boundary and |
Marko Mikulicic |
0:c0ecb8bf28eb | 11167 | * whether decoded byte had continuation bit set. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11168 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11169 | } while (++i < sizeof(size_t) && (p[i - 1] & 0x80)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11170 | *llen = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11172 | return string_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11175 | /* Return number of bytes to store length */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11176 | V7_PRIVATE int calc_llen(size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11177 | int n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11178 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11179 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11180 | n++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11181 | } while (len >>= 7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11182 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11183 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11184 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11186 | V7_PRIVATE int encode_varint(size_t len, unsigned char *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11187 | int i, llen = calc_llen(len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11189 | for (i = 0; i < llen; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11190 | p[i] = (len & 0x7f) | (i < llen - 1 ? 0x80 : 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11191 | len >>= 7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11194 | return llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11197 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11198 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11199 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11200 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11201 | #line 1 "v7/src/tokenizer.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11202 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11203 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11204 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 11205 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 11206 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11207 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11208 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11209 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11210 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11211 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11212 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11214 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11216 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11217 | * NOTE(lsm): Must be in the same order as enum for keywords. See comment |
Marko Mikulicic |
0:c0ecb8bf28eb | 11218 | * for function get_tok() for rationale for that. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11219 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11220 | static const struct v7_vec_const s_keywords[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11221 | V7_VEC("break"), V7_VEC("case"), V7_VEC("catch"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11222 | V7_VEC("continue"), V7_VEC("debugger"), V7_VEC("default"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11223 | V7_VEC("delete"), V7_VEC("do"), V7_VEC("else"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11224 | V7_VEC("false"), V7_VEC("finally"), V7_VEC("for"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11225 | V7_VEC("function"), V7_VEC("if"), V7_VEC("in"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11226 | V7_VEC("instanceof"), V7_VEC("new"), V7_VEC("null"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11227 | V7_VEC("return"), V7_VEC("switch"), V7_VEC("this"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11228 | V7_VEC("throw"), V7_VEC("true"), V7_VEC("try"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11229 | V7_VEC("typeof"), V7_VEC("var"), V7_VEC("void"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11230 | V7_VEC("while"), V7_VEC("with")}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11232 | V7_PRIVATE int is_reserved_word_token(enum v7_tok tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11233 | return tok >= TOK_BREAK && tok <= TOK_WITH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11234 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11236 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11237 | * Move ptr to the next token, skipping comments and whitespaces. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11238 | * Return number of new line characters detected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11239 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11240 | V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11241 | const char *s = *ptr, *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11242 | int num_lines = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11243 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11244 | while (s != p && s < src_end && *s != '\0' && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11245 | (isspace((unsigned char) *s) || *s == '/')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11246 | p = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11247 | while (s < src_end && *s != '\0' && isspace((unsigned char) *s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11248 | if (*s == '\n') num_lines++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11249 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11251 | if ((s + 1) < src_end && s[0] == '/' && s[1] == '/') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11252 | s += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11253 | while (s < src_end && s[0] != '\0' && s[0] != '\n') s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11254 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11255 | if ((s + 1) < src_end && s[0] == '/' && s[1] == '*') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11256 | s += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11257 | while (s < src_end && s[0] != '\0' && !(s[-1] == '/' && s[-2] == '*')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11258 | if (s[0] == '\n') num_lines++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11259 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11260 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11261 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11262 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11263 | *ptr = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11264 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11265 | return num_lines; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11266 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11268 | /* Advance `s` pointer to the end of identifier */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11269 | static void ident(const char **s, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11270 | const unsigned char *p = (unsigned char *) *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11271 | int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11272 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11274 | while ((const char *) p < src_end && p[0] != '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11275 | if (p[0] == '$' || p[0] == '_' || isalnum(p[0])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11276 | /* $, _, or any alphanumeric are valid identifier characters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11277 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11278 | } else if ((const char *) (p + 5) < src_end && p[0] == '\\' && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11279 | p[1] == 'u' && isxdigit(p[2]) && isxdigit(p[3]) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11280 | isxdigit(p[4]) && isxdigit(p[5])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11281 | /* Unicode escape, \uXXXX . Could be used like "var \u0078 = 1;" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11282 | p += 6; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11283 | } else if ((n = chartorune(&r, (char *) p)) > 1 && isalpharune(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11284 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11285 | * TODO(dfrank): the chartorune() call above can read `p` past the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11286 | * src_end, so it might crash on incorrect code. The solution would be |
Marko Mikulicic |
0:c0ecb8bf28eb | 11287 | * to modify `chartorune()` to accept src_end argument as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11288 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11289 | /* Unicode alphanumeric character */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11290 | p += n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11291 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11292 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11293 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11294 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11296 | *s = (char *) p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11297 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11299 | static enum v7_tok kw(const char *s, size_t len, int ntoks, enum v7_tok tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11300 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11302 | for (i = 0; i < ntoks; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11303 | if (s_keywords[(tok - TOK_BREAK) + i].len == len && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11304 | memcmp(s_keywords[(tok - TOK_BREAK) + i].p + 1, s + 1, len - 1) == 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11305 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11306 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11308 | return i == ntoks ? TOK_IDENTIFIER : (enum v7_tok)(tok + i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11309 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11311 | static enum v7_tok punct1(const char **s, const char *src_end, int ch1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11312 | enum v7_tok tok1, enum v7_tok tok2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11313 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11314 | if (*s < src_end && **s == ch1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11315 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11316 | return tok1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11317 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11318 | return tok2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11319 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11322 | static enum v7_tok punct2(const char **s, const char *src_end, int ch1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11323 | enum v7_tok tok1, int ch2, enum v7_tok tok2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11324 | enum v7_tok tok3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11325 | if ((*s + 2) < src_end && s[0][1] == ch1 && s[0][2] == ch2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11326 | (*s) += 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11327 | return tok2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11328 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11330 | return punct1(s, src_end, ch1, tok1, tok3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11331 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11333 | static enum v7_tok punct3(const char **s, const char *src_end, int ch1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11334 | enum v7_tok tok1, int ch2, enum v7_tok tok2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11335 | enum v7_tok tok3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11336 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11337 | if (*s < src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11338 | if (**s == ch1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11339 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11340 | return tok1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11341 | } else if (**s == ch2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11342 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11343 | return tok2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11345 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11346 | return tok3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11347 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11348 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11349 | static void parse_number(const char *s, const char **end, double *num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11350 | *num = cs_strtod(s, (char **) end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11351 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11352 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11353 | static enum v7_tok parse_str_literal(const char **p, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11354 | const char *s = *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11355 | int quote = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11357 | if (s < src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11358 | quote = *s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11361 | /* Scan string literal, handle escape sequences */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11362 | for (; s < src_end && *s != '\0' && *s != quote; s++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11363 | if (*s == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11364 | switch (s[1]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11365 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11366 | case 'f': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11367 | case 'n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11368 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11369 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11370 | case 'v': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11371 | case '\\': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11372 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11373 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11374 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11375 | if (s[1] == quote) s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11376 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11377 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11378 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11381 | if (s < src_end && *s == quote) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11382 | s++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11383 | *p = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11384 | return TOK_STRING_LITERAL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11385 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11386 | return TOK_END_OF_INPUT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11387 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11390 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11391 | * This function is the heart of the tokenizer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11392 | * Organized as a giant switch statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11393 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11394 | * Switch statement is by the first character of the input stream. If first |
Marko Mikulicic |
0:c0ecb8bf28eb | 11395 | * character begins with a letter, it could be either keyword or identifier. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11396 | * get_tok() calls ident() which shifts `s` pointer to the end of the word. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11397 | * Now, tokenizer knows that the word begins at `p` and ends at `s`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11398 | * It calls function kw() to scan over the keywords that start with `p[0]` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11399 | * letter. Therefore, keyword tokens and keyword strings must be in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11400 | * same order, to let kw() function work properly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11401 | * If kw() finds a keyword match, it returns keyword token. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11402 | * Otherwise, it returns TOK_IDENTIFIER. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11403 | * NOTE(lsm): `prev_tok` is a previously parsed token. It is needed for |
Marko Mikulicic |
0:c0ecb8bf28eb | 11404 | * correctly parsing regex literals. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11405 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11406 | V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11407 | enum v7_tok prev_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11408 | const char *p = *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11410 | if (p >= src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11411 | return TOK_END_OF_INPUT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11412 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11413 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11414 | switch (*p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11415 | /* Letters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11416 | case 'a': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11417 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11418 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11419 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11420 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11421 | return kw(p, *s - p, 1, TOK_BREAK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11422 | case 'c': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11423 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11424 | return kw(p, *s - p, 3, TOK_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11425 | case 'd': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11426 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11427 | return kw(p, *s - p, 4, TOK_DEBUGGER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11428 | case 'e': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11429 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11430 | return kw(p, *s - p, 1, TOK_ELSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11431 | case 'f': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11432 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11433 | return kw(p, *s - p, 4, TOK_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11434 | case 'g': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11435 | case 'h': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11436 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11437 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11438 | case 'i': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11439 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11440 | return kw(p, *s - p, 3, TOK_IF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11441 | case 'j': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11442 | case 'k': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11443 | case 'l': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11444 | case 'm': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11445 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11446 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11447 | case 'n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11448 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11449 | return kw(p, *s - p, 2, TOK_NEW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11450 | case 'o': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11451 | case 'p': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11452 | case 'q': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11453 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11454 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11455 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11456 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11457 | return kw(p, *s - p, 1, TOK_RETURN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11458 | case 's': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11459 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11460 | return kw(p, *s - p, 1, TOK_SWITCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11461 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11462 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11463 | return kw(p, *s - p, 5, TOK_THIS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11464 | case 'u': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11465 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11466 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11467 | case 'v': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11468 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11469 | return kw(p, *s - p, 2, TOK_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11470 | case 'w': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11471 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11472 | return kw(p, *s - p, 2, TOK_WHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11473 | case 'x': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11474 | case 'y': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11475 | case 'z': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11476 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11477 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11478 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11479 | case '_': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11480 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11481 | case 'A': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11482 | case 'B': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11483 | case 'C': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11484 | case 'D': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11485 | case 'E': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11486 | case 'F': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11487 | case 'G': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11488 | case 'H': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11489 | case 'I': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11490 | case 'J': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11491 | case 'K': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11492 | case 'L': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11493 | case 'M': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11494 | case 'N': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11495 | case 'O': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11496 | case 'P': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11497 | case 'Q': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11498 | case 'R': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11499 | case 'S': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11500 | case 'T': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11501 | case 'U': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11502 | case 'V': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11503 | case 'W': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11504 | case 'X': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11505 | case 'Y': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11506 | case 'Z': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11507 | case '\\': /* Identifier may start with unicode escape sequence */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11508 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11509 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11511 | /* Numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11512 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11513 | case '1': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11514 | case '2': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11515 | case '3': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11516 | case '4': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11517 | case '5': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11518 | case '6': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11519 | case '7': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11520 | case '8': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11521 | case '9': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11522 | parse_number(p, s, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11523 | return TOK_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11525 | /* String literals */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11526 | case '\'': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11527 | case '"': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11528 | return parse_str_literal(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11529 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11530 | /* Punctuators */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11531 | case '=': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11532 | return punct2(s, src_end, '=', TOK_EQ, '=', TOK_EQ_EQ, TOK_ASSIGN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11533 | case '!': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11534 | return punct2(s, src_end, '=', TOK_NE, '=', TOK_NE_NE, TOK_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11536 | case '%': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11537 | return punct1(s, src_end, '=', TOK_REM_ASSIGN, TOK_REM); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11538 | case '*': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11539 | return punct1(s, src_end, '=', TOK_MUL_ASSIGN, TOK_MUL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11540 | case '/': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11541 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11542 | * TOK_DIV, TOK_DIV_ASSIGN, and TOK_REGEX_LITERAL start with `/` char. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11543 | * Division can happen after an expression. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11544 | * In expressions like this: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11545 | * a /= b; c /= d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11546 | * things between slashes is NOT a regex literal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11547 | * The switch below catches all cases where division happens. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11548 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11549 | switch (prev_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11550 | case TOK_CLOSE_CURLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11551 | case TOK_CLOSE_PAREN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11552 | case TOK_CLOSE_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11553 | case TOK_IDENTIFIER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11554 | case TOK_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11555 | return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11556 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11557 | /* Not a division - this is a regex. Scan until closing slash */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11558 | for (p++; p < src_end && *p != '\0' && *p != '\n'; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11559 | if (*p == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11560 | /* Skip escape sequence */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11561 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11562 | } else if (*p == '/') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11563 | /* This is a closing slash */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11564 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11565 | /* Skip regex flags */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11566 | while (*p == 'g' || *p == 'i' || *p == 'm') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11567 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11568 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11569 | *s = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11570 | return TOK_REGEX_LITERAL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11571 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11572 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11573 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11574 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11575 | return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11576 | case '^': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11577 | return punct1(s, src_end, '=', TOK_XOR_ASSIGN, TOK_XOR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11578 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11579 | case '+': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11580 | return punct3(s, src_end, '+', TOK_PLUS_PLUS, '=', TOK_PLUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11581 | TOK_PLUS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11582 | case '-': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11583 | return punct3(s, src_end, '-', TOK_MINUS_MINUS, '=', TOK_MINUS_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11584 | TOK_MINUS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11585 | case '&': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11586 | return punct3(s, src_end, '&', TOK_LOGICAL_AND, '=', TOK_AND_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11587 | TOK_AND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11588 | case '|': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11589 | return punct3(s, src_end, '|', TOK_LOGICAL_OR, '=', TOK_OR_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11590 | TOK_OR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11592 | case '<': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11593 | if (*s + 1 < src_end && s[0][1] == '=') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11594 | (*s) += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11595 | return TOK_LE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11596 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11597 | return punct2(s, src_end, '<', TOK_LSHIFT, '=', TOK_LSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11598 | TOK_LT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11599 | case '>': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11600 | if (*s + 1 < src_end && s[0][1] == '=') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11601 | (*s) += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11602 | return TOK_GE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11603 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11604 | if (*s + 3 < src_end && s[0][1] == '>' && s[0][2] == '>' && |
Marko Mikulicic |
0:c0ecb8bf28eb | 11605 | s[0][3] == '=') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11606 | (*s) += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11607 | return TOK_URSHIFT_ASSIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11608 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11609 | if (*s + 2 < src_end && s[0][1] == '>' && s[0][2] == '>') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11610 | (*s) += 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11611 | return TOK_URSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11612 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11613 | return punct2(s, src_end, '>', TOK_RSHIFT, '=', TOK_RSHIFT_ASSIGN, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11614 | TOK_GT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11616 | case '{': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11617 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11618 | return TOK_OPEN_CURLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11619 | case '}': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11620 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11621 | return TOK_CLOSE_CURLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11622 | case '(': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11623 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11624 | return TOK_OPEN_PAREN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11625 | case ')': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11626 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11627 | return TOK_CLOSE_PAREN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11628 | case '[': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11629 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11630 | return TOK_OPEN_BRACKET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11631 | case ']': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11632 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11633 | return TOK_CLOSE_BRACKET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11634 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11635 | switch (*(*s + 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11636 | /* Numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11637 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11638 | case '1': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11639 | case '2': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11640 | case '3': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11641 | case '4': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11642 | case '5': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11643 | case '6': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11644 | case '7': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11645 | case '8': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11646 | case '9': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11647 | parse_number(p, s, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11648 | return TOK_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11649 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11650 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11651 | return TOK_DOT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11652 | case ';': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11653 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11654 | return TOK_SEMICOLON; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11655 | case ':': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11656 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11657 | return TOK_COLON; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11658 | case '?': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11659 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11660 | return TOK_QUESTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11661 | case '~': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11662 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11663 | return TOK_TILDA; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11664 | case ',': |
Marko Mikulicic |
0:c0ecb8bf28eb | 11665 | (*s)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11666 | return TOK_COMMA; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11668 | default: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11669 | /* Handle unicode variables */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11670 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11671 | if (chartorune(&r, *s) > 1 && isalpharune(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11672 | ident(s, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11673 | return TOK_IDENTIFIER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11674 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11675 | return TOK_END_OF_INPUT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11678 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11680 | #ifdef TEST_RUN |
Marko Mikulicic |
0:c0ecb8bf28eb | 11681 | int main(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11682 | const char *src = |
Marko Mikulicic |
0:c0ecb8bf28eb | 11683 | "for (var fo++ = -1; /= <= 1.17; x<<) { == <<=, 'x')} " |
Marko Mikulicic |
0:c0ecb8bf28eb | 11684 | "Infinity %=x<<=2"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11685 | const char *src_end = src + strlen(src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11686 | enum v7_tok tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11687 | double num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11688 | const char *p = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11690 | skip_to_next_tok(&src, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11691 | while ((tok = get_tok(&src, src_end, &num)) != TOK_END_OF_INPUT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11692 | printf("%d [%.*s]\n", tok, (int) (src - p), p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11693 | skip_to_next_tok(&src, src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11694 | p = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11695 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11696 | printf("%d [%.*s]\n", tok, (int) (src - p), p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 11697 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11698 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11700 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11702 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11703 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11704 | #line 1 "v7/src/ast.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11705 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11706 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11707 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 11708 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 11709 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11711 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11712 | /* Amalgamated: #include "common/mbuf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11713 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11714 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11715 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11716 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11717 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11718 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11719 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11721 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11723 | #ifdef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 11724 | typedef uint32_t ast_skip_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11725 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 11726 | typedef uint16_t ast_skip_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11727 | #define AST_SKIP_MAX UINT16_MAX |
Marko Mikulicic |
0:c0ecb8bf28eb | 11728 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11730 | #ifndef V7_DISABLE_AST_TAG_NAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 11731 | #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11732 | { (name), (has_varint), (has_inlined), (num_skips), (num_subtrees) } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11733 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 11734 | #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11735 | { (has_varint), (has_inlined), (num_skips), (num_subtrees) } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11736 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 11737 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11738 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11739 | * The structure of AST nodes cannot be described in portable ANSI C, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11740 | * since they are variable length and packed (unaligned). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11741 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11742 | * Here each node's body is described with a pseudo-C structure notation. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11743 | * The pseudo type `child` represents a variable length byte sequence |
Marko Mikulicic |
0:c0ecb8bf28eb | 11744 | * representing a fully serialized child node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11745 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11746 | * `child body[]` represents a sequence of such subtrees. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11747 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11748 | * Pseudo-labels, such as `end:` represent the targets of skip fields |
Marko Mikulicic |
0:c0ecb8bf28eb | 11749 | * with the same name (e.g. `ast_skip_t end`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11750 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11751 | * Skips allow skipping a subtree or sequence of subtrees. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11752 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11753 | * Sequences of subtrees (i.e. `child []`) have to be terminated by a skip: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11754 | * they don't have a termination tag; all nodes whose position is before the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11755 | * skip are part of the sequence. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11756 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11757 | * Skips are encoded as network-byte-order 16-bit offsets counted from the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11758 | * first byte of the node body (i.e. not counting the tag itself). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11759 | * This currently limits the the maximum size of a function body to 64k. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11760 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11761 | * Notes: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11762 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11763 | * - Some nodes contain skips just for performance or because it simplifies |
Marko Mikulicic |
0:c0ecb8bf28eb | 11764 | * the implementation of the interpreter. For example, technically, the FOR |
Marko Mikulicic |
0:c0ecb8bf28eb | 11765 | * node doesn't need the `body` skip in order to be correctly traversed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11766 | * However, being able to quickly skip the `iter` expression is useful |
Marko Mikulicic |
0:c0ecb8bf28eb | 11767 | * also because it allows the interpreter to avoid traversing the expression |
Marko Mikulicic |
0:c0ecb8bf28eb | 11768 | * subtree without evaluating it, just in order to find the next subtree. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11769 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11770 | * - The name `skip` was chosen because `offset` was too overloaded in general |
Marko Mikulicic |
0:c0ecb8bf28eb | 11771 | * and label` is part of our domain model (i.e. JS has a label AST node type). |
Marko Mikulicic |
0:c0ecb8bf28eb | 11772 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11773 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11774 | * So, each node has a mandatory field: *tag* (see `enum ast_tag`), and a |
Marko Mikulicic |
0:c0ecb8bf28eb | 11775 | * number of optional fields. Whether the node has one or another optional |
Marko Mikulicic |
0:c0ecb8bf28eb | 11776 | * field is determined by the *node descriptor*: `struct ast_node_def`. For |
Marko Mikulicic |
0:c0ecb8bf28eb | 11777 | * each node type (i.e. for each element of `enum ast_tag`) there is a |
Marko Mikulicic |
0:c0ecb8bf28eb | 11778 | * corresponding descriptor: see `ast_node_defs`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11779 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11780 | * Optional fields are: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11781 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11782 | * - *varint*: a varint-encoded number. At the moment, this field is only used |
Marko Mikulicic |
0:c0ecb8bf28eb | 11783 | * together with the next field: inlined data, and a varint number determines |
Marko Mikulicic |
0:c0ecb8bf28eb | 11784 | * the inlined data length. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11785 | * - *inlined data*: a node-specific data. Size of it is determined by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11786 | * previous field: varint. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11787 | * - *skips*: as explained above, these are integer offsets, encoded in |
Marko Mikulicic |
0:c0ecb8bf28eb | 11788 | * big-endian. The number of skips is determined by the node descriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 11789 | * (`struct ast_node_def`). The size of each skip is either 16 or 32 bits, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11790 | * depending on whether the macro `V7_LARGE_AST` is set. The order of skips |
Marko Mikulicic |
0:c0ecb8bf28eb | 11791 | * is determined by the `enum ast_which_skip`. See examples below for |
Marko Mikulicic |
0:c0ecb8bf28eb | 11792 | * clarity. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11793 | * - *subtrees*: child nodes. Some nodes have fixed number of child nodes; in |
Marko Mikulicic |
0:c0ecb8bf28eb | 11794 | * this case, the descriptor has non-zero field `num_subtrees`. Otherwise, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11795 | * `num_subtrees` is zero, and consumer handles child nodes one by one, until |
Marko Mikulicic |
0:c0ecb8bf28eb | 11796 | * the end of the node is reached (end of the node is determined by the `end` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11797 | * skip) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11798 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11799 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11800 | * Examples: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11801 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11802 | * Let's start from the very easy example script: "300;" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11803 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11804 | * Tree looks as follows: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11805 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11806 | * $ ./v7 -e "300;" -t |
Marko Mikulicic |
0:c0ecb8bf28eb | 11807 | * SCRIPT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11808 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11809 | * NUM 300 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11810 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11811 | * Binary data is: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11812 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11813 | * $ ./v7 -e "300;" -b | od -A n -t x1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11814 | * 56 07 41 53 54 56 31 30 00 01 00 09 00 00 13 03 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11815 | * 33 30 30 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11816 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11817 | * Let's break it down and examine: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11818 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11819 | * - 56 07 41 53 54 56 31 30 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11820 | * Just a format prefix: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11821 | * Null-terminated string: `"V\007ASTV10"` (see `BIN_AST_SIGNATURE`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11822 | * - 01 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11823 | * AST tag: `AST_SCRIPT`. As you see in `ast_node_defs` below, node of |
Marko Mikulicic |
0:c0ecb8bf28eb | 11824 | * this type has neither *varint* nor *inlined data* fields, but it has |
Marko Mikulicic |
0:c0ecb8bf28eb | 11825 | * 2 skips: `end` and `next`. `end` is a skip to the end of the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 11826 | * node (`SCRIPT`), and `next` will be explained below. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11827 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11828 | * The size of each skip depends on whether `V7_LARGE_AST` is defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11829 | * If it is, then size is 32 bit, otherwise it's 16 bit. In this |
Marko Mikulicic |
0:c0ecb8bf28eb | 11830 | * example, we have 16-bit skips. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11831 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11832 | * The order of skips is determined by the `enum ast_which_skip`. If you |
Marko Mikulicic |
0:c0ecb8bf28eb | 11833 | * check, you'll see that `AST_END_SKIP` is 0, and `AST_VAR_NEXT_SKIP` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11834 | * is 1. So, `end` skip fill be the first, and `next` will be the second: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11835 | * - 00 09 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11836 | * `end` skip: 9 bytes. It's the size of the whole `SCRIPT` data. So, if |
Marko Mikulicic |
0:c0ecb8bf28eb | 11837 | * we have an index of the `ASC_SCRIPT` tag, we can just add this skip |
Marko Mikulicic |
0:c0ecb8bf28eb | 11838 | * (9) to this index, and therefore skip over the whole node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11839 | * - 00 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11840 | * `next` skip. `next` actually means "next variable node": since |
Marko Mikulicic |
0:c0ecb8bf28eb | 11841 | * variables are hoisted in JavaScript, when the interpreter starts |
Marko Mikulicic |
0:c0ecb8bf28eb | 11842 | * executing a top-level code or any function, it needs to get a list of |
Marko Mikulicic |
0:c0ecb8bf28eb | 11843 | * all defined variables. The `SCRIPT` node has a "skip" to the first |
Marko Mikulicic |
0:c0ecb8bf28eb | 11844 | * `var` or `function` declaration, which, in turn, has a "skip" to the |
Marko Mikulicic |
0:c0ecb8bf28eb | 11845 | * next one, etc. If there is no next `var` declaration, then 0 is |
Marko Mikulicic |
0:c0ecb8bf28eb | 11846 | * stored. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11847 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11848 | * In our super-simple script, we have no `var` neither `function` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11849 | * declarations, so, this skip is 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11850 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11851 | * Now, the body of our SCRIPT node goes, which contains child nodes: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11852 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11853 | * - 13 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11854 | * AST tag: `AST_NUM`. Look at the `ast_node_defs`, and we'll see that |
Marko Mikulicic |
0:c0ecb8bf28eb | 11855 | * nodes of this type don't have any skips, but they do have the varint |
Marko Mikulicic |
0:c0ecb8bf28eb | 11856 | * field and the inlined data. Here we go: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11857 | * - 03 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11858 | * Varint value: 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11859 | * - 33 30 30 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11860 | * UTF-8 string "300" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11861 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11862 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 11863 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11864 | * The next example is a bit more interesting: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11865 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11866 | * var foo, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11867 | * bar = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11868 | * foo = 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11869 | * var baz = 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11870 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11871 | * Tree: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11872 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11873 | * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -t |
Marko Mikulicic |
0:c0ecb8bf28eb | 11874 | * SCRIPT |
Marko Mikulicic |
0:c0ecb8bf28eb | 11875 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11876 | * VAR |
Marko Mikulicic |
0:c0ecb8bf28eb | 11877 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11878 | * VAR_DECL foo |
Marko Mikulicic |
0:c0ecb8bf28eb | 11879 | * NOP |
Marko Mikulicic |
0:c0ecb8bf28eb | 11880 | * VAR_DECL bar |
Marko Mikulicic |
0:c0ecb8bf28eb | 11881 | * NUM 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11882 | * ASSIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 11883 | * IDENT foo |
Marko Mikulicic |
0:c0ecb8bf28eb | 11884 | * NUM 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11885 | * VAR |
Marko Mikulicic |
0:c0ecb8bf28eb | 11886 | * /- [...] -/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11887 | * VAR_DECL baz |
Marko Mikulicic |
0:c0ecb8bf28eb | 11888 | * NUM 4 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11889 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11890 | * Binary: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11891 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11892 | * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -b | od -A n -t x1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11893 | * 56 07 41 53 54 56 31 30 00 01 00 2d 00 05 02 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11894 | * 12 00 1c 03 03 66 6f 6f 00 03 03 62 61 72 13 01 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11895 | * 31 07 14 03 66 6f 6f 13 01 33 02 00 0c 00 00 03 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11896 | * 03 62 61 7a 13 01 34 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11897 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11898 | * Break it down: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11899 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11900 | * - 56 07 41 53 54 56 31 30 00 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11901 | * `"V\007ASTV10"` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11902 | * - 01: AST tag: `AST_SCRIPT` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11903 | * - 00 2d: `end` skip: 0x2d = 45 bytes |
Marko Mikulicic |
0:c0ecb8bf28eb | 11904 | * - 00 05: `next` skip: an offset from `AST_SCRIPT` byte to the first |
Marko Mikulicic |
0:c0ecb8bf28eb | 11905 | * `var` declaration. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11906 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11907 | * Now, body of the SCRIPT node begins, which contains child nodes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 11908 | * and the first node is the var declaration `var foo, bar=1;`: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11909 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11910 | * SCRIPT node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11911 | * - 02: AST tag: `AST_VAR` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11912 | * - 00 12: `end` skip: 18 bytes from tag byte to the end of current node |
Marko Mikulicic |
0:c0ecb8bf28eb | 11913 | * - 00 1c: `next` skip: 28 bytes from tag byte to the next `var` node |
Marko Mikulicic |
0:c0ecb8bf28eb | 11914 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11915 | * The VAR node contains arbitrary number of child nodes, so, consumer |
Marko Mikulicic |
0:c0ecb8bf28eb | 11916 | * takes advantage of the `end` skip. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11917 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11918 | * VAR node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11919 | * - 03: AST tag: `AST_VAR_DECL` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11920 | * - 03: Varint value: 3 (the length of the inlined data: a variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 11921 | *name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11922 | * - 66 6f 6f: UTF-8 string: "foo" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11923 | * - 00: AST tag: `AST_NOP` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11924 | * Since we haven't provided any value to store into `foo`, NOP |
Marko Mikulicic |
0:c0ecb8bf28eb | 11925 | * without any additional data is stored in AST. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11926 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11927 | * - 03: AST tag: `AST_VAR_DECL` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11928 | * - 03: Varint value: 3 (the length of the inlined data: a variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 11929 | *name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11930 | * - 62 61 72: UTF-8 string: "bar" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11931 | * - 13: AST tag: `AST_NUM` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11932 | * - 01: Varint value: 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11933 | * - 31: UTF-8 string "1" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11934 | * VAR body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11935 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11936 | * - 07: AST tag: `AST_ASSIGN` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11937 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11938 | * The ASSIGN node has fixed number of subrees: 2 (lvalue and rvalue), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11939 | * so there's no `end` skip. |
Marko Mikulicic |
0:c0ecb8bf28eb | 11940 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11941 | * ASSIGN node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11942 | * - 14: AST tag: `AST_IDENT` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11943 | * - 03: Varint value: 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11944 | * - 66 6f 6f: UTF-8 string: "foo" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11945 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11946 | * - 13: AST tag: `AST_NUM` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11947 | * - 01: Varint value: 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11948 | * - 33: UTF-8 string: "3" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11949 | * ASSIGN body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11950 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11951 | * - 02: AST tag: `AST_VAR` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11952 | * - 00 0c: `end` skip: 12 bytes from tag byte to the end of current node |
Marko Mikulicic |
0:c0ecb8bf28eb | 11953 | * - 00 00: `next` skip: no more `var` nodes |
Marko Mikulicic |
0:c0ecb8bf28eb | 11954 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11955 | * VAR node body: {{{ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11956 | * - 03: AST tag: `AST_VAR_DECL` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11957 | * - 03: Varint value: 3 (the length of the inlined data: a variable |
Marko Mikulicic |
0:c0ecb8bf28eb | 11958 | *name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 11959 | * - 62 61 7a: UTF-8 string: "baz" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11960 | * - 13: AST tag: `AST_NUM` |
Marko Mikulicic |
0:c0ecb8bf28eb | 11961 | * - 01: Varint value: 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 11962 | * - 34: UTF-8 string "4" |
Marko Mikulicic |
0:c0ecb8bf28eb | 11963 | * VAR body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11964 | * SCRIPT body end }}} |
Marko Mikulicic |
0:c0ecb8bf28eb | 11965 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 11966 | * -------------------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 11967 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11969 | const struct ast_node_def ast_node_defs[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11970 | AST_ENTRY("NOP", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11971 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 11972 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11973 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11974 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11975 | * ast_skip_t first_var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11976 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11977 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11978 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11979 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11980 | AST_ENTRY("SCRIPT", 0, 0, 2, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11981 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11982 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11983 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11984 | * ast_skip_t next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11985 | * child decls[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11986 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 11987 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11988 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11989 | AST_ENTRY("VAR", 0, 0, 2, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11990 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11991 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 11992 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11993 | * char name[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11994 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 11995 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 11996 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 11997 | AST_ENTRY("VAR_DECL", 1, 1, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 11998 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 11999 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12000 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12001 | * char name[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12002 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12003 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12004 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12005 | AST_ENTRY("FUNC_DECL", 1, 1, 0, 1), |
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 end_true; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12010 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12011 | * child iftrue[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12012 | * end_true: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12013 | * child iffalse[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12014 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12015 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12016 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12017 | AST_ENTRY("IF", 0, 0, 2, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12018 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12019 | * TODO(mkm) distinguish function expressions |
Marko Mikulicic |
0:c0ecb8bf28eb | 12020 | * from function statements. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12021 | * Function statements behave like vars and need a |
Marko Mikulicic |
0:c0ecb8bf28eb | 12022 | * next field for hoisting. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12023 | * We can also ignore the name for function expressions |
Marko Mikulicic |
0:c0ecb8bf28eb | 12024 | * if it's only needed for debugging. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12025 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 12026 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12027 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12028 | * ast_skip_t first_var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12029 | * ast_skip_t body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12030 | * child name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12031 | * child params[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12032 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12033 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12034 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12035 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12036 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12037 | AST_ENTRY("FUNC", 0, 0, 3, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12038 | AST_ENTRY("ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12039 | AST_ENTRY("REM_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12040 | AST_ENTRY("MUL_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12041 | AST_ENTRY("DIV_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12042 | AST_ENTRY("XOR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12043 | AST_ENTRY("PLUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12044 | AST_ENTRY("MINUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12045 | AST_ENTRY("OR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12046 | AST_ENTRY("AND_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12047 | AST_ENTRY("LSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12048 | AST_ENTRY("RSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12049 | AST_ENTRY("URSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12050 | AST_ENTRY("NUM", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12051 | AST_ENTRY("IDENT", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12052 | AST_ENTRY("STRING", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12053 | AST_ENTRY("REGEX", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12054 | AST_ENTRY("LABEL", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12056 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12057 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12058 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12059 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12060 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12061 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12062 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12063 | AST_ENTRY("SEQ", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12064 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12065 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12066 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12067 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12068 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12069 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12070 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12071 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12072 | AST_ENTRY("WHILE", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12073 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12074 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12075 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12076 | * ast_skip_t cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12077 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12078 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12079 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12080 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12081 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12082 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12083 | AST_ENTRY("DOWHILE", 0, 0, 2, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12084 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12085 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12086 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12087 | * ast_skip_t body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12088 | * child init; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12089 | * child cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12090 | * child iter; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12091 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12092 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12093 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12094 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12095 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12096 | AST_ENTRY("FOR", 0, 0, 2, 3), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12097 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12098 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12099 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12100 | * ast_skip_t dummy; // allows to quickly promote a for to a for in |
Marko Mikulicic |
0:c0ecb8bf28eb | 12101 | * child var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12102 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12103 | * child dummy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12104 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12105 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12106 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12107 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12108 | AST_ENTRY("FOR_IN", 0, 0, 2, 3), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12109 | AST_ENTRY("COND", 0, 0, 0, 3), /* struct { child cond, iftrue, iffalse; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12110 | AST_ENTRY("DEBUGGER", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12111 | AST_ENTRY("BREAK", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12113 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12114 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12115 | * child label; // TODO(mkm): inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 12116 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12117 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12118 | AST_ENTRY("LAB_BREAK", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12119 | AST_ENTRY("CONTINUE", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12121 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12122 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12123 | * child label; // TODO(mkm): inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 12124 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12125 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12126 | AST_ENTRY("LAB_CONTINUE", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12127 | AST_ENTRY("RETURN", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12128 | AST_ENTRY("VAL_RETURN", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12129 | AST_ENTRY("THROW", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12131 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12132 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12133 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12134 | * ast_skip_t catch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12135 | * ast_skip_t finally; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12136 | * child try[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12137 | * catch: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12138 | * child var; // TODO(mkm): inline |
Marko Mikulicic |
0:c0ecb8bf28eb | 12139 | * child catch[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12140 | * finally: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12141 | * child finally[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12142 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12143 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12144 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12145 | AST_ENTRY("TRY", 0, 0, 3, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12146 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12147 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12148 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12149 | * ast_skip_t def; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12150 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12151 | * child cases[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12152 | * def: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12153 | * child default?; // optional |
Marko Mikulicic |
0:c0ecb8bf28eb | 12154 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12155 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12156 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12157 | AST_ENTRY("SWITCH", 0, 0, 2, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12158 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12159 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12160 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12161 | * child val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12162 | * child stmts[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12163 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12164 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12165 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12166 | AST_ENTRY("CASE", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12167 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12168 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12169 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12170 | * child stmts[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12171 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12172 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12173 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12174 | AST_ENTRY("DEFAULT", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12175 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12176 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12177 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12178 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12179 | * child body[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12180 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12181 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12182 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12183 | AST_ENTRY("WITH", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12184 | AST_ENTRY("LOG_OR", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12185 | AST_ENTRY("LOG_AND", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12186 | AST_ENTRY("OR", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12187 | AST_ENTRY("XOR", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12188 | AST_ENTRY("AND", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12189 | AST_ENTRY("EQ", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12190 | AST_ENTRY("EQ_EQ", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12191 | AST_ENTRY("NE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12192 | AST_ENTRY("NE_NE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12193 | AST_ENTRY("LE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12194 | AST_ENTRY("LT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12195 | AST_ENTRY("GE", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12196 | AST_ENTRY("GT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12197 | AST_ENTRY("IN", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12198 | AST_ENTRY("INSTANCEOF", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12199 | AST_ENTRY("LSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12200 | AST_ENTRY("RSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12201 | AST_ENTRY("URSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12202 | AST_ENTRY("ADD", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12203 | AST_ENTRY("SUB", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12204 | AST_ENTRY("REM", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12205 | AST_ENTRY("MUL", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12206 | AST_ENTRY("DIV", 0, 0, 0, 2), /* struct { child left, right; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12207 | AST_ENTRY("POS", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12208 | AST_ENTRY("NEG", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12209 | AST_ENTRY("NOT", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12210 | AST_ENTRY("LOGICAL_NOT", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12211 | AST_ENTRY("VOID", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12212 | AST_ENTRY("DELETE", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12213 | AST_ENTRY("TYPEOF", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12214 | AST_ENTRY("PREINC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12215 | AST_ENTRY("PREDEC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12216 | AST_ENTRY("POSTINC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12217 | AST_ENTRY("POSTDEC", 0, 0, 0, 1), /* struct { child expr; } */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12218 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12219 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12220 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12221 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12222 | * char ident[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12223 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12224 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12225 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12226 | AST_ENTRY("MEMBER", 1, 1, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12227 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12228 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12229 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12230 | * child index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12231 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12232 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12233 | AST_ENTRY("INDEX", 0, 0, 0, 2), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12234 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12235 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12236 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12237 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12238 | * child args[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12239 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12240 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12241 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12242 | AST_ENTRY("CALL", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12243 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12244 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12245 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12246 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12247 | * child args[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12248 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12249 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12250 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12251 | AST_ENTRY("NEW", 0, 0, 1, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12252 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12253 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12254 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12255 | * child elements[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12256 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12257 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12258 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12259 | AST_ENTRY("ARRAY", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12260 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12261 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12262 | * ast_skip_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12263 | * child props[]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12264 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12265 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12266 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12267 | AST_ENTRY("OBJECT", 0, 0, 1, 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12268 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12269 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12270 | * varint len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12271 | * char name[len]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12272 | * child expr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12273 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12274 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12275 | AST_ENTRY("PROP", 1, 1, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12276 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12277 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12278 | * child func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12279 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12280 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12281 | AST_ENTRY("GETTER", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12282 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12283 | * struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12284 | * child func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12285 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12286 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12287 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12288 | AST_ENTRY("SETTER", 0, 0, 0, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 12289 | AST_ENTRY("THIS", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12290 | AST_ENTRY("TRUE", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12291 | AST_ENTRY("FALSE", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12292 | AST_ENTRY("NULL", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12293 | AST_ENTRY("UNDEF", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12294 | AST_ENTRY("USE_STRICT", 0, 0, 0, 0), /* struct {} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12295 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12297 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12298 | * A flag which is used to mark node's tag byte if the node has line number |
Marko Mikulicic |
0:c0ecb8bf28eb | 12299 | * data encoded (varint after skips). See `ast_get_line_no()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12300 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12301 | #define AST_TAG_LINENO_PRESENT 0x80 |
Marko Mikulicic |
0:c0ecb8bf28eb | 12302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12303 | V7_STATIC_ASSERT(AST_MAX_TAG < 256, ast_tag_should_fit_in_char); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12304 | V7_STATIC_ASSERT(AST_MAX_TAG == ARRAY_SIZE(ast_node_defs), bad_node_defs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12305 | V7_STATIC_ASSERT(AST_MAX_TAG <= AST_TAG_LINENO_PRESENT, bad_AST_LINE_NO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12307 | #if V7_ENABLE_FOOTPRINT_REPORT |
Marko Mikulicic |
0:c0ecb8bf28eb | 12308 | const size_t ast_node_defs_size = sizeof(ast_node_defs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12309 | const size_t ast_node_defs_count = ARRAY_SIZE(ast_node_defs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12310 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12312 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12313 | * Converts a given byte `t` (which should be read from the AST data buffer) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12314 | * into `enum ast_tag`. This function is needed because tag might be marked |
Marko Mikulicic |
0:c0ecb8bf28eb | 12315 | * with the `AST_TAG_LINENO_PRESENT` flag; the returned tag is always unmarked, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12316 | * and if the flag was indeed set, `lineno_present` is set to 1; otherwise |
Marko Mikulicic |
0:c0ecb8bf28eb | 12317 | * it is set to 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12318 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 12319 | * `lineno_present` is allowed to be NULL, if the caller doesn't care of the |
Marko Mikulicic |
0:c0ecb8bf28eb | 12320 | * line number presence. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12321 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12322 | static enum ast_tag uint8_to_tag(uint8_t t, uint8_t *lineno_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12323 | if (t & AST_TAG_LINENO_PRESENT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12324 | t &= ~AST_TAG_LINENO_PRESENT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12325 | if (lineno_present != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12326 | *lineno_present = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12327 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12328 | } else if (lineno_present != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12329 | *lineno_present = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12330 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12331 | return (enum ast_tag) t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12332 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12334 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 12335 | ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12336 | uint8_t t = (uint8_t) tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12337 | const struct ast_node_def *d = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12338 | ast_off_t cur = pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12340 | assert(tag < AST_MAX_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12341 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12342 | mbuf_insert(&a->mbuf, cur, (char *) &t, sizeof(t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12343 | cur += sizeof(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12345 | mbuf_insert(&a->mbuf, cur, NULL, sizeof(ast_skip_t) * d->num_skips); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12346 | cur += sizeof(ast_skip_t) * d->num_skips; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12347 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12348 | if (d->num_skips) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12349 | ast_set_skip(a, pos + 1, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12350 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12352 | return pos + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12355 | V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12356 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12357 | a->mbuf.buf[tag_off] = tag | (a->mbuf.buf[tag_off] & 0x80); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12358 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12360 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 12361 | V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12362 | ast_off_t ln_off = tag_off + 1 /* tag byte */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12363 | int llen = calc_llen(line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12365 | ast_move_to_inlined_data(a, &ln_off); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12366 | mbuf_insert(&a->mbuf, ln_off, NULL, llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12367 | encode_varint(line_no, (unsigned char *) (a->mbuf.buf + ln_off)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12369 | assert(a->mbuf.buf[tag_off] < AST_MAX_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12370 | a->mbuf.buf[tag_off] |= AST_TAG_LINENO_PRESENT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12371 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12372 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12374 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 12375 | ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12376 | return ast_modify_skip(a, pos, a->mbuf.len, skip); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12377 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12379 | V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12380 | ast_off_t where, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12381 | enum ast_which_skip skip) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12382 | uint8_t *p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12383 | ast_skip_t delta = where - pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12384 | #ifndef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 12385 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12386 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12387 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12388 | assert(pos <= where); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12390 | #ifndef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 12391 | /* the value of delta overflowed, therefore the ast is not useable */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12392 | if (where - pos > AST_SKIP_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12393 | a->has_overflow = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12394 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12395 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12397 | /* assertion, to be optimizable out */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12398 | assert((int) skip < def->num_skips); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12400 | #ifdef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 12401 | p[0] = delta >> 24; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12402 | p[1] = delta >> 16 & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12403 | p[2] = delta >> 8 & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12404 | p[3] = delta & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12405 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12406 | p[0] = delta >> 8; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12407 | p[1] = delta & 0xff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12408 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12409 | return where; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12410 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12412 | V7_PRIVATE ast_off_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 12413 | ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12414 | uint8_t *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12415 | assert(pos + skip * sizeof(ast_skip_t) < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12417 | p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12418 | #ifdef V7_LARGE_AST |
Marko Mikulicic |
0:c0ecb8bf28eb | 12419 | return pos + (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12420 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12421 | return pos + (p[1] | p[0] << 8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12422 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12423 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12425 | V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12426 | enum ast_tag ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12427 | assert(*ppos < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12429 | ret = uint8_to_tag(*(a->mbuf.buf + (*ppos)++), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12431 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12432 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12434 | V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12435 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12436 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12437 | assert(*ppos - 1 < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12438 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12439 | ast_move_to_inlined_data(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12441 | /* skip varint + inline data, if present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12442 | if (def->has_varint) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12443 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12444 | size_t slen = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12445 | *ppos += llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12446 | if (def->has_inlined) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12447 | *ppos += slen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12448 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12449 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12450 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12451 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12452 | V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12453 | enum ast_tag tag, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12454 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12455 | const struct ast_node_def *d = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12457 | ast_off_t offset = ast_insert_node(a, pos, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12459 | assert(d->has_inlined); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12461 | embed_string(&a->mbuf, offset + sizeof(ast_skip_t) * d->num_skips, name, len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12462 | EMBSTR_UNESCAPE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12464 | return offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12465 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12467 | V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12468 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12469 | * by default we'll return 0, meaning that the AST node does not contain line |
Marko Mikulicic |
0:c0ecb8bf28eb | 12470 | * number data |
Marko Mikulicic |
0:c0ecb8bf28eb | 12471 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12472 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12474 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 12475 | uint8_t lineno_present; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12476 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), &lineno_present); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12478 | if (lineno_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12479 | /* line number is present, so, let's decode it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12480 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12481 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12482 | /* skip skips */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12483 | pos += ast_node_defs[tag].num_skips * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12484 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12485 | /* get line number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12486 | ret = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12488 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12489 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12490 | (void) pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12491 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12493 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12494 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12495 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12496 | V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12497 | uint8_t lineno_present = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12498 | enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), &lineno_present); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12499 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12500 | assert(*ppos - 1 < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12502 | /* skip skips */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12503 | *ppos += def->num_skips * sizeof(ast_skip_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12505 | /* skip line_no, if present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12506 | if (lineno_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12507 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12508 | int line_no = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12509 | *ppos += llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12511 | (void) line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12512 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12513 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12514 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12515 | V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12516 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12517 | assert(pos < a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12519 | ast_move_to_inlined_data(a, &pos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12521 | *n = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12522 | return a->mbuf.buf + pos + llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12525 | V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12526 | double ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12527 | char *str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12528 | size_t str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12529 | char buf[12]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12530 | char *p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12531 | str = ast_get_inlined_data(a, pos, &str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12532 | assert(str + str_len <= a->mbuf.buf + a->mbuf.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12533 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12534 | if (str_len > sizeof(buf) - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12535 | p = (char *) malloc(str_len + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12536 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12537 | strncpy(p, str, str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12538 | p[str_len] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12539 | ret = cs_strtod(p, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12540 | if (p != buf) free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12541 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12544 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 12545 | static void comment_at_depth(FILE *fp, const char *fmt, int depth, ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12546 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12547 | STATIC char buf[256]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12548 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12549 | va_start(ap, depth); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12550 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12551 | c_vsnprintf(buf, sizeof(buf), fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12552 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12553 | for (i = 0; i < depth; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12554 | fprintf(fp, " "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12555 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12556 | fprintf(fp, "/* [%s] */\n", buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12557 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12558 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12560 | V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12561 | enum ast_tag tag = ast_fetch_tag(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12562 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12563 | ast_off_t skips = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12564 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12565 | ast_move_to_children(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12567 | for (i = 0; i < def->num_subtrees; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12568 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12569 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12571 | if (def->num_skips > AST_END_SKIP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12572 | ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12574 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12575 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12576 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12577 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12578 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12580 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 12581 | V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12582 | int depth) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12583 | enum ast_tag tag = ast_fetch_tag(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12584 | const struct ast_node_def *def = &ast_node_defs[tag]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12585 | ast_off_t skips = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12586 | size_t slen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12587 | int i, llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12589 | for (i = 0; i < depth; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12590 | fprintf(fp, " "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12593 | #ifndef V7_DISABLE_AST_TAG_NAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12594 | fprintf(fp, "%s", def->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12595 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12596 | fprintf(fp, "TAG_%d", tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12597 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12599 | if (def->has_inlined) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12600 | ast_off_t pos_tmp = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12601 | ast_move_to_inlined_data(a, &pos_tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12603 | slen = decode_varint((unsigned char *) a->mbuf.buf + pos_tmp, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12604 | fprintf(fp, " %.*s\n", (int) slen, a->mbuf.buf + pos_tmp + llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12605 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12606 | fprintf(fp, "\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12607 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12608 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12609 | ast_move_to_children(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12611 | for (i = 0; i < def->num_subtrees; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12612 | ast_dump_tree(fp, a, ppos, depth + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12613 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12615 | if (ast_node_defs[tag].num_skips) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12616 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12617 | * first skip always encodes end of the last children sequence. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12618 | * so unless we care how the subtree sequences are grouped together |
Marko Mikulicic |
0:c0ecb8bf28eb | 12619 | * (and we currently don't) we can just read until the end of that skip. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12620 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12621 | ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12623 | comment_at_depth(fp, "...", depth + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12624 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12625 | int s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12626 | for (s = ast_node_defs[tag].num_skips - 1; s > 0; s--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12627 | if (*ppos == ast_get_skip(a, skips, (enum ast_which_skip) s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12628 | comment_at_depth(fp, "%d ->", depth + 1, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12629 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12631 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12632 | ast_dump_tree(fp, a, ppos, depth + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12633 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12634 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12636 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12638 | V7_PRIVATE void ast_init(struct ast *ast, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12639 | mbuf_init(&ast->mbuf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12640 | ast->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12641 | ast->has_overflow = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12642 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12644 | V7_PRIVATE void ast_optimize(struct ast *ast) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12645 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12646 | * leave one trailing byte so that literals can be |
Marko Mikulicic |
0:c0ecb8bf28eb | 12647 | * null terminated on the fly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12648 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12649 | mbuf_resize(&ast->mbuf, ast->mbuf.len + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12650 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12652 | V7_PRIVATE void ast_free(struct ast *ast) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12653 | mbuf_free(&ast->mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12654 | ast->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12655 | ast->has_overflow = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12656 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12657 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12658 | V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12659 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12660 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12661 | if (a->refcnt != 0) a->refcnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12663 | if (a->refcnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12664 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12665 | v7->function_arena_ast_size -= a->mbuf.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12666 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12667 | ast_free(a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12668 | free(a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12669 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12670 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12672 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12673 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12674 | #line 1 "v7/src/bcode.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 12675 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12676 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12677 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 12678 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 12679 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12680 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12681 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12682 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12683 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12684 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12685 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12686 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12687 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12688 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12689 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12690 | /* Amalgamated: #include "v7/src/shdata.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12692 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12693 | * TODO(dfrank): implement `bcode_serialize_*` more generically, so that they |
Marko Mikulicic |
0:c0ecb8bf28eb | 12694 | * can write to buffer instead of a `FILE`. Then, remove a need for mmap here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 12695 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12696 | #if CS_PLATFORM == CS_P_UNIX |
Marko Mikulicic |
0:c0ecb8bf28eb | 12697 | #include <sys/mman.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 12698 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12700 | #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12701 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12702 | static const char *op_names[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12703 | "DROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12704 | "DUP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12705 | "2DUP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12706 | "SWAP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12707 | "STASH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12708 | "UNSTASH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12709 | "SWAP_DROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12710 | "PUSH_UNDEFINED", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12711 | "PUSH_NULL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12712 | "PUSH_THIS", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12713 | "PUSH_TRUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12714 | "PUSH_FALSE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12715 | "PUSH_ZERO", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12716 | "PUSH_ONE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12717 | "PUSH_LIT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12718 | "NOT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12719 | "LOGICAL_NOT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12720 | "NEG", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12721 | "POS", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12722 | "ADD", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12723 | "SUB", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12724 | "REM", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12725 | "MUL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12726 | "DIV", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12727 | "LSHIFT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12728 | "RSHIFT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12729 | "URSHIFT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12730 | "OR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12731 | "XOR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12732 | "AND", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12733 | "EQ_EQ", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12734 | "EQ", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12735 | "NE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12736 | "NE_NE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12737 | "LT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12738 | "LE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12739 | "GT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12740 | "GE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12741 | "INSTANCEOF", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12742 | "TYPEOF", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12743 | "IN", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12744 | "GET", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12745 | "SET", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12746 | "SET_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12747 | "GET_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12748 | "SAFE_GET_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12749 | "JMP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12750 | "JMP_TRUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12751 | "JMP_FALSE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12752 | "JMP_TRUE_DROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12753 | "JMP_IF_CONTINUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12754 | "CREATE_OBJ", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12755 | "CREATE_ARR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12756 | "PUSH_PROP_ITER_CTX", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12757 | "NEXT_PROP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12758 | "FUNC_LIT", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12759 | "CALL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12760 | "NEW", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12761 | "CHECK_CALL", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12762 | "RET", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12763 | "DELETE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12764 | "DELETE_VAR", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12765 | "TRY_PUSH_CATCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12766 | "TRY_PUSH_FINALLY", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12767 | "TRY_PUSH_LOOP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12768 | "TRY_PUSH_SWITCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12769 | "TRY_POP", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12770 | "AFTER_FINALLY", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12771 | "THROW", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12772 | "BREAK", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12773 | "CONTINUE", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12774 | "ENTER_CATCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12775 | "EXIT_CATCH", |
Marko Mikulicic |
0:c0ecb8bf28eb | 12776 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12777 | /* clang-format on */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12779 | V7_STATIC_ASSERT(OP_MAX == ARRAY_SIZE(op_names), bad_op_names); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12780 | V7_STATIC_ASSERT(OP_MAX <= _OP_LINE_NO, bad_OP_LINE_NO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12781 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12783 | static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode, FILE *out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12785 | static size_t bcode_ops_append(struct bcode_builder *bbuilder, const void *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12786 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12787 | size_t ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12788 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12789 | bbuilder->v7->bcode_ops_size -= bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12790 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12791 | ret = mbuf_append(&bbuilder->ops, buf, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12792 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12793 | bbuilder->v7->bcode_ops_size += bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12794 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12795 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12796 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12798 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12799 | * Initialize bcode builder. The `bcode` should be already initialized by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 12800 | * caller, and should be empty (i.e. should not own any ops, literals, etc) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12801 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 12802 | * TODO(dfrank) : probably make `bcode_builder_init()` to initialize `bcode` |
Marko Mikulicic |
0:c0ecb8bf28eb | 12803 | * as well |
Marko Mikulicic |
0:c0ecb8bf28eb | 12804 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12805 | V7_PRIVATE void bcode_builder_init(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12806 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12807 | struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12808 | memset(bbuilder, 0x00, sizeof(*bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12809 | bbuilder->v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12810 | bbuilder->bcode = bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12812 | mbuf_init(&bbuilder->ops, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12813 | mbuf_init(&bbuilder->lit, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12816 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12817 | * Finalize bcode builder: propagate data to the bcode and transfer the |
Marko Mikulicic |
0:c0ecb8bf28eb | 12818 | * ownership from builder to bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 12819 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12820 | V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12821 | mbuf_trim(&bbuilder->ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12822 | bbuilder->bcode->ops.p = bbuilder->ops.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12823 | bbuilder->bcode->ops.len = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12824 | mbuf_init(&bbuilder->ops, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12826 | mbuf_trim(&bbuilder->lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12827 | bbuilder->bcode->lit.p = bbuilder->lit.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12828 | bbuilder->bcode->lit.len = bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12829 | mbuf_init(&bbuilder->lit, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12831 | memset(bbuilder, 0x00, sizeof(*bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12832 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12834 | #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 12835 | V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12836 | char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12837 | char *p = *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12839 | assert(*p < OP_MAX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12840 | fprintf(f, "%zu: %s", (size_t)(p - bcode->ops.p), op_names[(uint8_t) *p]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12841 | switch (*p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12842 | case OP_PUSH_LIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12843 | case OP_SAFE_GET_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12844 | case OP_GET_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12845 | case OP_SET_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12846 | size_t idx = bcode_get_varint(&p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12847 | fprintf(f, "(%lu): ", (unsigned long) idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12848 | v7_fprint(f, v7, ((val_t *) bcode->lit.p)[idx]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12849 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12850 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12851 | case OP_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12852 | case OP_NEW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12853 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12854 | fprintf(f, "(%d)", *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12855 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12856 | case OP_JMP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12857 | case OP_JMP_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12858 | case OP_JMP_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12859 | case OP_JMP_TRUE_DROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12860 | case OP_JMP_IF_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12861 | case OP_TRY_PUSH_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12862 | case OP_TRY_PUSH_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12863 | case OP_TRY_PUSH_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12864 | case OP_TRY_PUSH_SWITCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12865 | bcode_off_t target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12866 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12867 | memcpy(&target, p, sizeof(target)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12868 | fprintf(f, "(%lu)", (unsigned long) target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12869 | p += sizeof(target) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12870 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12871 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12872 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 12873 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12874 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12875 | fprintf(f, "\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12876 | *ops = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12878 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12880 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 12881 | V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12882 | char *p = bcode_end_names(bcode->ops.p, bcode->names_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12883 | char *end = bcode->ops.p + bcode->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12884 | for (; p < end; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12885 | dump_op(v7, f, bcode, &p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12887 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12888 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12890 | V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12891 | void *filename, uint8_t filename_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12892 | memset(bcode, 0x00, sizeof(*bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12893 | bcode->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12894 | bcode->args_cnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12895 | bcode->strict_mode = strict_mode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12896 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12897 | bcode->filename = filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12898 | bcode->filename_in_rom = filename_in_rom; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12899 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12900 | (void) filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12901 | (void) filename_in_rom; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12902 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12903 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12905 | V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12906 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12907 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 12908 | if (!bcode->ops_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12909 | v7->bcode_ops_size -= bcode->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12912 | v7->bcode_lit_total_size -= bcode->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12913 | if (bcode->deserialized) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12914 | v7->bcode_lit_deser_size -= bcode->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12916 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12918 | if (!bcode->ops_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12919 | free(bcode->ops.p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12921 | memset(&bcode->ops, 0x00, sizeof(bcode->ops)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12923 | free(bcode->lit.p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12924 | memset(&bcode->lit, 0x00, sizeof(bcode->lit)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12926 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12927 | if (!bcode->filename_in_rom && bcode->filename != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12928 | shdata_release((struct shdata *) bcode->filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12929 | bcode->filename = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12930 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12931 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12933 | bcode->refcnt = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12934 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12936 | V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12937 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12938 | if (!b->frozen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12939 | b->refcnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12940 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12943 | V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12944 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12945 | if (b->frozen) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12946 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12947 | assert(b->refcnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12948 | if (b->refcnt != 0) b->refcnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12950 | if (b->refcnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12951 | bcode_free(v7, b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12952 | free(b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12953 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12954 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12956 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12957 | V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12958 | const char *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12959 | if (bcode->filename_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12960 | ret = (const char *) bcode->filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12961 | } else if (bcode->filename != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12962 | ret = (const char *) shdata_get_payload((struct shdata *) bcode->filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12963 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12964 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12965 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12966 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12968 | V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12969 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 12970 | dst->filename_in_rom = src->filename_in_rom; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12971 | dst->filename = src->filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12972 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12973 | if (src->filename != NULL && !src->filename_in_rom) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12974 | shdata_retain((struct shdata *) dst->filename); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12975 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12976 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 12977 | (void) dst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12978 | (void) src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12979 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12980 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12982 | V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12983 | bcode_ops_append(bbuilder, &op, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12984 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12985 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12986 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 12987 | V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 12988 | int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 12989 | int offset = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 12990 | bcode_add_varint(bbuilder, (line_no << 1) | 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12991 | bbuilder->ops.buf[offset] = msb_lsb_swap(bbuilder->ops.buf[offset]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12992 | assert(bbuilder->ops.buf[offset] & _OP_LINE_NO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 12993 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 12994 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 12995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 12996 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 12997 | * Appends varint-encoded integer to the `ops` mbuf |
Marko Mikulicic |
0:c0ecb8bf28eb | 12998 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 12999 | V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13000 | int k = calc_llen(value); /* Calculate how many bytes length takes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13001 | int offset = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13003 | /* Allocate buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13004 | bcode_ops_append(bbuilder, NULL, k); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13005 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13006 | /* Write value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13007 | encode_varint(value, (unsigned char *) bbuilder->ops.buf + offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13008 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13010 | V7_PRIVATE size_t bcode_get_varint(char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13011 | size_t ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13012 | int len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13013 | (*ops)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13014 | ret = decode_varint((unsigned char *) *ops, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13015 | *ops += len - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13016 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13017 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13018 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13019 | static int bcode_is_inline_string(struct v7 *v7, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13020 | uint64_t tag = val & V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13021 | if (v7->is_precompiling && v7_is_string(val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13022 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13023 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13024 | return tag == V7_TAG_STRING_I || tag == V7_TAG_STRING_5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13025 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13027 | static int bcode_is_inline_func(struct v7 *v7, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13028 | return (v7->is_precompiling && is_js_function(val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13029 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13031 | static int bcode_is_inline_regexp(struct v7 *v7, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13032 | return (v7->is_precompiling && v7_is_regexp(v7, val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13033 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13035 | V7_PRIVATE lit_t bcode_add_lit(struct bcode_builder *bbuilder, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13036 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13037 | memset(&lit, 0, sizeof(lit)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13039 | if (bcode_is_inline_string(bbuilder->v7, val) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 13040 | bcode_is_inline_func(bbuilder->v7, val) || v7_is_number(val) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 13041 | bcode_is_inline_regexp(bbuilder->v7, val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13042 | /* literal should be inlined (it's `bcode_op_lit()` who does this) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13043 | lit.mode = LIT_MODE__INLINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13044 | lit.v.inline_val = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13045 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13046 | /* literal will now be added to the literal table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13047 | lit.mode = LIT_MODE__TABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13048 | lit.v.lit_idx = bbuilder->lit.len / sizeof(val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13050 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 13051 | bbuilder->v7->bcode_lit_total_size -= bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13052 | if (bbuilder->bcode->deserialized) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13053 | bbuilder->v7->bcode_lit_deser_size -= bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13054 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13055 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13057 | mbuf_append(&bbuilder->lit, &val, sizeof(val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13059 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13060 | * immediately propagate current lit buffer to the bcode, so that GC will |
Marko Mikulicic |
0:c0ecb8bf28eb | 13061 | * be aware of it |
Marko Mikulicic |
0:c0ecb8bf28eb | 13062 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13063 | bbuilder->bcode->lit.p = bbuilder->lit.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13064 | bbuilder->bcode->lit.len = bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13066 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 13067 | bbuilder->v7->bcode_lit_total_size += bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13068 | if (bbuilder->bcode->deserialized) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13069 | bbuilder->v7->bcode_lit_deser_size += bbuilder->lit.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13070 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13071 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13072 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13073 | return lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13074 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13076 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13077 | V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13078 | val_t ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13079 | memcpy(&ret, bcode->lit.p + (size_t) idx * sizeof(ret), sizeof(ret)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13080 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13082 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13084 | static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13085 | const char *data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13086 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13087 | V7_PRIVATE v7_val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 13088 | bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13089 | struct v7_vec *vec = &bcode->lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13090 | size_t idx = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13091 | switch (idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13092 | case BCODE_INLINE_STRING_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13093 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13094 | size_t len = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13095 | res = v7_mk_string( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13096 | v7, (const char *) *ops + 1 /*skip BCODE_INLINE_STRING_TYPE_TAG*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13097 | len, !bcode->ops_in_rom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13098 | *ops += len + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13099 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13101 | case BCODE_INLINE_NUMBER_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13102 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13103 | memcpy(&res, *ops + 1 /*skip BCODE_INLINE_NUMBER_TYPE_TAG*/, sizeof(res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13104 | *ops += sizeof(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13105 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13106 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13107 | case BCODE_INLINE_FUNC_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13108 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13109 | * Create half-done function: without scope but _with_ prototype. Scope |
Marko Mikulicic |
0:c0ecb8bf28eb | 13110 | * will be set by `bcode_instantiate_function()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13111 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13112 | * The fact that the prototype is already set will make |
Marko Mikulicic |
0:c0ecb8bf28eb | 13113 | * `bcode_instantiate_function()` just set scope on this function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13114 | * instead of creating a new one. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13115 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13116 | val_t res = mk_js_function(v7, NULL, v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13117 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13118 | /* Create bcode in this half-done function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13119 | struct v7_js_function *func = get_js_function_struct(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13121 | func->bcode = (struct bcode *) calloc(1, sizeof(*func->bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13122 | bcode_init(func->bcode, bcode->strict_mode, NULL /* will be set below */, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13123 | 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13124 | bcode_copy_filename_from(func->bcode, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13125 | retain_bcode(v7, func->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13126 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13127 | /* deserialize the function's bcode from `ops` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13128 | *ops = (char *) bcode_deserialize_func( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13129 | v7, func->bcode, *ops + 1 /*skip BCODE_INLINE_FUNC_TYPE_TAG*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13131 | /* decrement *ops, because it will be incremented by `eval_bcode` soon */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13132 | *ops -= 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13134 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13135 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13136 | case BCODE_INLINE_REGEXP_TYPE_TAG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13137 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 13138 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13139 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13140 | size_t len_src, len_flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13141 | char *buf_src, *buf_flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13143 | len_src = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13144 | buf_src = *ops + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13145 | *ops += len_src + 1 /* nul term */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13147 | len_flags = bcode_get_varint(ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13148 | buf_flags = *ops + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13149 | *ops += len_flags + 1 /* nul term */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13151 | rcode = v7_mk_regexp(v7, buf_src, len_src, buf_flags, len_flags, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13152 | assert(rcode == V7_OK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13153 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13154 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13155 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13156 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 13157 | fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13158 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13159 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13160 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13161 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13162 | return ((val_t *) vec->p)[idx - BCODE_MAX_INLINE_TYPE_TAG]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13163 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13164 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13166 | V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13167 | lit_t lit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13168 | bcode_op(bbuilder, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13170 | switch (lit.mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13171 | case LIT_MODE__TABLE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13172 | bcode_add_varint(bbuilder, lit.v.lit_idx + BCODE_MAX_INLINE_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13173 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13175 | case LIT_MODE__INLINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13176 | if (v7_is_string(lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13177 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13178 | const char *s = v7_get_string(bbuilder->v7, &lit.v.inline_val, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13179 | bcode_add_varint(bbuilder, BCODE_INLINE_STRING_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13180 | bcode_add_varint(bbuilder, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13181 | bcode_ops_append(bbuilder, s, len + 1 /* nul term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13182 | } else if (v7_is_number(lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13183 | bcode_add_varint(bbuilder, BCODE_INLINE_NUMBER_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13184 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13185 | * TODO(dfrank): we can save some memory by storing string |
Marko Mikulicic |
0:c0ecb8bf28eb | 13186 | * representation of a number here, instead of wasting 8 bytes for each |
Marko Mikulicic |
0:c0ecb8bf28eb | 13187 | * number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13188 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13189 | * Alternatively, we can add more tags for integers, like |
Marko Mikulicic |
0:c0ecb8bf28eb | 13190 | * `BCODE_INLINE_S08_TYPE_TAG`, `BCODE_INLINE_S16_TYPE_TAG`, etc, since |
Marko Mikulicic |
0:c0ecb8bf28eb | 13191 | * integers are the most common numbers for sure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13192 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13193 | bcode_ops_append(bbuilder, &lit.v.inline_val, sizeof(lit.v.inline_val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13194 | } else if (is_js_function(lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13195 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13196 | * TODO(dfrank): implement `bcode_serialize_*` more generically, so |
Marko Mikulicic |
0:c0ecb8bf28eb | 13197 | * that they can write to buffer instead of a `FILE`. Then, remove this |
Marko Mikulicic |
0:c0ecb8bf28eb | 13198 | * workaround with `CS_PLATFORM == CS_P_UNIX`, `tmpfile()`, etc. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13199 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13200 | #if CS_PLATFORM == CS_P_UNIX |
Marko Mikulicic |
0:c0ecb8bf28eb | 13201 | struct v7_js_function *func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13202 | FILE *fp = tmpfile(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13203 | long len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13204 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13205 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13206 | func = get_js_function_struct(lit.v.inline_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13207 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13208 | /* we inline functions if only we're precompiling */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13209 | assert(bbuilder->v7->is_precompiling); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13210 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13211 | bcode_add_varint(bbuilder, BCODE_INLINE_FUNC_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13212 | bcode_serialize_func(bbuilder->v7, func->bcode, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13214 | fflush(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13216 | len = ftell(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13218 | p = (char *) mmap(NULL, len, PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13220 | bcode_ops_append(bbuilder, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13222 | fclose(fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13223 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13224 | } else if (v7_is_regexp(bbuilder->v7, lit.v.inline_val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13225 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 13226 | struct v7_regexp *rp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13227 | v7_get_regexp_struct(bbuilder->v7, lit.v.inline_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13228 | bcode_add_varint(bbuilder, BCODE_INLINE_REGEXP_TYPE_TAG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13229 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13230 | /* append regexp source */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13231 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13232 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13233 | const char *buf = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13234 | v7_get_string(bbuilder->v7, &rp->regexp_string, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13235 | bcode_add_varint(bbuilder, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13236 | bcode_ops_append(bbuilder, buf, len + 1 /* nul term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13237 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13238 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13239 | /* append regexp flags */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13240 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13241 | char buf[_V7_REGEXP_MAX_FLAGS_LEN + 1 /* nul term */]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13242 | size_t len = get_regexp_flags_str(bbuilder->v7, rp, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13243 | bcode_add_varint(bbuilder, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13244 | bcode_ops_append(bbuilder, buf, len + 1 /* nul term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13245 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13246 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 13247 | fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13248 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13249 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13250 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13251 | /* invalid type of inlined value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13252 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13253 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13254 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13256 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13257 | /* invalid literal mode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13258 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13259 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13260 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13261 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13263 | V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13264 | bcode_op_lit(bbuilder, OP_PUSH_LIT, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13265 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13267 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 13268 | /*V7_PRIVATE*/ enum v7_err |
Marko Mikulicic |
0:c0ecb8bf28eb | 13269 | bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13270 | size_t *idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13271 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13272 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13273 | size_t ops_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13275 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13276 | * if name length is not provided, assume it's null-terminated and calculate |
Marko Mikulicic |
0:c0ecb8bf28eb | 13277 | * it |
Marko Mikulicic |
0:c0ecb8bf28eb | 13278 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13279 | if (len == ~((size_t) 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13280 | len = strlen(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13281 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13283 | /* index at which to put name. If not provided, we'll append at the end */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13284 | if (idx != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13285 | ops_index = *idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13286 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13287 | ops_index = bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13288 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13290 | /* calculate how much varint len will take */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13291 | llen = calc_llen(len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13293 | /* reserve space in `ops` buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13294 | mbuf_insert(&bbuilder->ops, ops_index, NULL, llen + len + 1 /*null-term*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13296 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13297 | char *ops = bbuilder->ops.buf + ops_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13299 | /* put varint len */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13300 | ops += encode_varint(len, (unsigned char *) ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13302 | /* put string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13303 | memcpy(ops, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13304 | ops += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13305 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13306 | /* null-terminate */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13307 | *ops++ = 0x00; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13309 | if (idx != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13310 | *idx = ops - bbuilder->ops.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13311 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13314 | /* maintain total number of names */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13315 | if (bbuilder->bcode->names_cnt < V7_NAMES_CNT_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13316 | bbuilder->bcode->names_cnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13317 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13318 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Too many local variables"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13319 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13321 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13324 | /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13325 | while (names_cnt--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13326 | ops = bcode_next_name(ops, NULL, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13327 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13328 | return ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13329 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13331 | V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13332 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13333 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13334 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13335 | len = decode_varint((unsigned char *) ops, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13337 | ops += llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13339 | if (pname != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13340 | *pname = ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13343 | if (plen != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13344 | *plen = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13345 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13347 | ops += len + 1 /*null-terminator*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13348 | return ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13349 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13351 | V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13352 | char *ops, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13353 | char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13354 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13356 | ops = bcode_next_name(ops, &name, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13358 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13359 | * If `ops` is in RAM, we create owned string, since the string may outlive |
Marko Mikulicic |
0:c0ecb8bf28eb | 13360 | * bcode. Otherwise (`ops` is in ROM), we create foreign string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13361 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13362 | *res = v7_mk_string(v7, name, len, !bcode->ops_in_rom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13364 | return ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13365 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13366 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13367 | V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13368 | return bbuilder->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13371 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13372 | * Appends a branch target and returns its location. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13373 | * This location can be updated with bcode_patch_target. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13374 | * To be issued following a JMP_* bytecode |
Marko Mikulicic |
0:c0ecb8bf28eb | 13375 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13376 | V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13377 | bcode_off_t pos = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13378 | bcode_off_t zero = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13379 | bcode_ops_append(bbuilder, &zero, sizeof(bcode_off_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13380 | return pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13381 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13383 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13384 | * Appends an op requiring a branch target. See bcode_add_target. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13385 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13386 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 13387 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 13388 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13389 | /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13390 | uint8_t op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13391 | bcode_op(bbuilder, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13392 | return bcode_add_target(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13394 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13395 | /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13396 | bcode_off_t label, bcode_off_t target) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13397 | memcpy(bbuilder->ops.buf + label, &target, sizeof(target)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13398 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13400 | /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13401 | FILE *out) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13402 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13403 | (void) bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13405 | fwrite(BIN_BCODE_SIGNATURE, sizeof(BIN_BCODE_SIGNATURE), 1, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13406 | bcode_serialize_func(v7, bcode, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13409 | static void bcode_serialize_varint(int n, FILE *out) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13410 | unsigned char buf[8]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13411 | int k = calc_llen(n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13412 | encode_varint(n, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13413 | fwrite(buf, k, 1, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13414 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13415 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13416 | static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13417 | FILE *out) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13418 | struct v7_vec *vec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13419 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13421 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13422 | * All literals should be inlined into `ops`, so we expect literals table |
Marko Mikulicic |
0:c0ecb8bf28eb | 13423 | * to be empty here |
Marko Mikulicic |
0:c0ecb8bf28eb | 13424 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13425 | assert(bcode->lit.len == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13427 | /* args_cnt */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13428 | bcode_serialize_varint(bcode->args_cnt, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13430 | /* names_cnt */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13431 | bcode_serialize_varint(bcode->names_cnt, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13432 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13433 | /* func_name_present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13434 | bcode_serialize_varint(bcode->func_name_present, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13436 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13437 | * bcode: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13438 | * <varint> // opcodes length |
Marko Mikulicic |
0:c0ecb8bf28eb | 13439 | * <opcode>* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13440 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13441 | vec = &bcode->ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13442 | bcode_serialize_varint(vec->len, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13443 | fwrite(vec->p, vec->len, 1, out); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13444 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13446 | static size_t bcode_deserialize_varint(const char **data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13447 | size_t ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13448 | int len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13449 | ret = decode_varint((const unsigned char *) (*data), &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13450 | *data += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13451 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13452 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13453 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13454 | static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13455 | const char *data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13456 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13457 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13459 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13461 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13462 | * before deserializing, set the corresponding flag, so that metrics will be |
Marko Mikulicic |
0:c0ecb8bf28eb | 13463 | * updated accordingly |
Marko Mikulicic |
0:c0ecb8bf28eb | 13464 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13465 | bcode->deserialized = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13467 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13468 | * In serialized functions, all literals are inlined into `ops`, so we don't |
Marko Mikulicic |
0:c0ecb8bf28eb | 13469 | * deserialize them here in any way |
Marko Mikulicic |
0:c0ecb8bf28eb | 13470 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13472 | /* get number of args */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13473 | bcode->args_cnt = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13475 | /* get number of names */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13476 | bcode->names_cnt = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13478 | /* get whether the function name is present in `names` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13479 | bcode->func_name_present = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13481 | /* get opcode size */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13482 | size = bcode_deserialize_varint(&data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13484 | bbuilder.ops.buf = (char *) data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13485 | bbuilder.ops.size = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13486 | bbuilder.ops.len = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13488 | bcode->ops_in_rom = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13490 | data += size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13492 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13493 | return data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13494 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13495 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13496 | V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13497 | const char *data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13498 | data = bcode_deserialize_func(v7, bcode, data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13499 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13500 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 13501 | #line 1 "v7/src/eval.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 13502 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13503 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13504 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 13505 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 13506 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13508 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13509 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13510 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13511 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13512 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13513 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13514 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13515 | /* Amalgamated: #include "v7/src/compiler.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13516 | /* Amalgamated: #include "v7/src/cyg_profile.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13517 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13518 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13519 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13520 | /* Amalgamated: #include "v7/src/shdata.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13521 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13522 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13523 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13525 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13526 | * Bcode offsets in "try stack" are stored in JS numbers, i.e. in `double`s. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13527 | * Apart from the offset itself, we also need some additional data: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13528 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13529 | * - type of the block that offset represents (`catch`, `finally`, `switch`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13530 | * or some loop) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13531 | * - size of the stack when the block is created (needed when throwing, since |
Marko Mikulicic |
0:c0ecb8bf28eb | 13532 | * if exception is thrown from the middle of the expression, the stack may |
Marko Mikulicic |
0:c0ecb8bf28eb | 13533 | * have any arbitrary length) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13534 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13535 | * We bake all this data into integer part of the double (53 bits) : |
Marko Mikulicic |
0:c0ecb8bf28eb | 13536 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13537 | * - 32 bits: bcode offset |
Marko Mikulicic |
0:c0ecb8bf28eb | 13538 | * - 3 bits: "tag": the type of the block |
Marko Mikulicic |
0:c0ecb8bf28eb | 13539 | * - 16 bits: stack size |
Marko Mikulicic |
0:c0ecb8bf28eb | 13540 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13542 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13543 | * Widths of data parts |
Marko Mikulicic |
0:c0ecb8bf28eb | 13544 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13545 | #define LBLOCK_OFFSET_WIDTH 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13546 | #define LBLOCK_TAG_WIDTH 3 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13547 | #define LBLOCK_STACK_SIZE_WIDTH 16 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13548 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13549 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13550 | * Shifts of data parts |
Marko Mikulicic |
0:c0ecb8bf28eb | 13551 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13552 | #define LBLOCK_OFFSET_SHIFT (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13553 | #define LBLOCK_TAG_SHIFT (LBLOCK_OFFSET_SHIFT + LBLOCK_OFFSET_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13554 | #define LBLOCK_STACK_SIZE_SHIFT (LBLOCK_TAG_SHIFT + LBLOCK_TAG_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13555 | #define LBLOCK_TOTAL_WIDTH (LBLOCK_STACK_SIZE_SHIFT + LBLOCK_STACK_SIZE_WIDTH) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13557 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13558 | * Masks of data parts |
Marko Mikulicic |
0:c0ecb8bf28eb | 13559 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13560 | #define LBLOCK_OFFSET_MASK \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13561 | ((int64_t)(((int64_t) 1 << LBLOCK_OFFSET_WIDTH) - 1) << LBLOCK_OFFSET_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13562 | #define LBLOCK_TAG_MASK \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13563 | ((int64_t)(((int64_t) 1 << LBLOCK_TAG_WIDTH) - 1) << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13564 | #define LBLOCK_STACK_SIZE_MASK \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13565 | ((int64_t)(((int64_t) 1 << LBLOCK_STACK_SIZE_WIDTH) - 1) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13566 | << LBLOCK_STACK_SIZE_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13567 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13568 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13569 | * Self-check: make sure all the data can fit into double's mantissa |
Marko Mikulicic |
0:c0ecb8bf28eb | 13570 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13571 | #if (LBLOCK_TOTAL_WIDTH > 53) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13572 | #error lblock width is too large, it can't fit into double's mantissa |
Marko Mikulicic |
0:c0ecb8bf28eb | 13573 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13575 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13576 | * Tags that are used for bcode offsets in "try stack" |
Marko Mikulicic |
0:c0ecb8bf28eb | 13577 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13578 | #define LBLOCK_TAG_CATCH ((int64_t) 0x01 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13579 | #define LBLOCK_TAG_FINALLY ((int64_t) 0x02 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13580 | #define LBLOCK_TAG_LOOP ((int64_t) 0x03 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13581 | #define LBLOCK_TAG_SWITCH ((int64_t) 0x04 << LBLOCK_TAG_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13582 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13583 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13584 | * Yields 32-bit bcode offset value |
Marko Mikulicic |
0:c0ecb8bf28eb | 13585 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13586 | #define LBLOCK_OFFSET(v) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13587 | ((bcode_off_t)(((v) &LBLOCK_OFFSET_MASK) >> LBLOCK_OFFSET_SHIFT)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13589 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13590 | * Yields tag value (unshifted, to be compared with macros like |
Marko Mikulicic |
0:c0ecb8bf28eb | 13591 | * `LBLOCK_TAG_CATCH`, etc) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13592 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13593 | #define LBLOCK_TAG(v) ((v) &LBLOCK_TAG_MASK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13594 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13595 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13596 | * Yields stack size |
Marko Mikulicic |
0:c0ecb8bf28eb | 13597 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13598 | #define LBLOCK_STACK_SIZE(v) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13599 | (((v) &LBLOCK_STACK_SIZE_MASK) >> LBLOCK_STACK_SIZE_SHIFT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13601 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13602 | * Yields `int64_t` value to be stored as a JavaScript number |
Marko Mikulicic |
0:c0ecb8bf28eb | 13603 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13604 | #define LBLOCK_ITEM_CREATE(offset, tag, stack_size) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13605 | ((int64_t)(offset) | (tag) | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13606 | (((int64_t)(stack_size)) << LBLOCK_STACK_SIZE_SHIFT)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13607 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13608 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13609 | * make sure `bcode_off_t` is just 32-bit, so that it can fit in double |
Marko Mikulicic |
0:c0ecb8bf28eb | 13610 | * with 3-bit tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 13611 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13612 | V7_STATIC_ASSERT((sizeof(bcode_off_t) * 8) == LBLOCK_OFFSET_WIDTH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13613 | wrong_size_of_bcode_off_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13615 | #define PUSH(v) stack_push(&v7->stack, v) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13616 | #define POP() stack_pop(&v7->stack) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13617 | #define TOS() stack_tos(&v7->stack) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13618 | #define SP() stack_sp(&v7->stack) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13620 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13621 | * Local-to-function block types that we might want to consider when unwinding |
Marko Mikulicic |
0:c0ecb8bf28eb | 13622 | * stack for whatever reason. see `unwind_local_blocks_stack()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13623 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13624 | enum local_block { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13625 | LOCAL_BLOCK_NONE = (0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13626 | LOCAL_BLOCK_CATCH = (1 << 0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13627 | LOCAL_BLOCK_FINALLY = (1 << 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13628 | LOCAL_BLOCK_LOOP = (1 << 2), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13629 | LOCAL_BLOCK_SWITCH = (1 << 3), |
Marko Mikulicic |
0:c0ecb8bf28eb | 13630 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13632 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13633 | * Like `V7_TRY()`, but to be used inside `eval_bcode()` only: you should |
Marko Mikulicic |
0:c0ecb8bf28eb | 13634 | * wrap all calls to cfunctions into `BTRY()` instead of `V7_TRY()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13635 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13636 | * If the provided function returns something other than `V7_OK`, this macro |
Marko Mikulicic |
0:c0ecb8bf28eb | 13637 | * calls `bcode_perform_throw`, which performs bcode stack unwinding. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13638 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13639 | #define BTRY(call) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13640 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13641 | enum v7_err _e = call; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13642 | (void) _you_should_use_BTRY_in_eval_bcode_only; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13643 | if (_e != V7_OK) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13644 | V7_TRY(bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13645 | goto op_done; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13646 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13647 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 13648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13649 | V7_PRIVATE void stack_push(struct mbuf *s, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13650 | mbuf_append(s, &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13651 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13652 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13653 | V7_PRIVATE val_t stack_pop(struct mbuf *s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13654 | assert(s->len >= sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13655 | s->len -= sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13656 | return *(val_t *) (s->buf + s->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13657 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13659 | V7_PRIVATE val_t stack_tos(struct mbuf *s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13660 | assert(s->len >= sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13661 | return *(val_t *) (s->buf + s->len - sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13662 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13664 | #ifdef V7_BCODE_TRACE_STACK |
Marko Mikulicic |
0:c0ecb8bf28eb | 13665 | V7_PRIVATE val_t stack_at(struct mbuf *s, size_t idx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13666 | assert(s->len >= sizeof(val_t) * idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13667 | return *(val_t *) (s->buf + s->len - sizeof(val_t) - idx * sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13668 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13669 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13671 | V7_PRIVATE int stack_sp(struct mbuf *s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13672 | return s->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13673 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13675 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13676 | * Delete a property with name `name`, `len` from an object `obj`. If the |
Marko Mikulicic |
0:c0ecb8bf28eb | 13677 | * object does not contain own property with the given `name`, moves to `obj`'s |
Marko Mikulicic |
0:c0ecb8bf28eb | 13678 | * prototype, and so on. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13679 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13680 | * If the property is eventually found, it is deleted, and `0` is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13681 | * Otherwise, `-1` is returned. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13682 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13683 | * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13684 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13685 | * See `v7_del()` as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13686 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13687 | static int del_property_deep(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13688 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13689 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13690 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13691 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13692 | for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13693 | int del_res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13694 | if ((del_res = v7_del(v7, obj, name, len)) != -1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13695 | return del_res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13696 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13697 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13698 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13701 | /* Visual studio 2012+ has signbit() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13702 | #if defined(_MSC_VER) && _MSC_VER < 1700 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13703 | static int signbit(double x) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13704 | double s = _copysign(1, x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13705 | return s < 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13706 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13707 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13708 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13709 | static double b_int_bin_op(enum opcode op, double a, double b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13710 | int32_t ia = isnan(a) || isinf(a) ? 0 : (int32_t)(int64_t) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13711 | int32_t ib = isnan(b) || isinf(b) ? 0 : (int32_t)(int64_t) b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13713 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13714 | case OP_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13715 | return (int32_t)((uint32_t) ia << ((uint32_t) ib & 31)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13716 | case OP_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13717 | return ia >> ((uint32_t) ib & 31); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13718 | case OP_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13719 | return (uint32_t) ia >> ((uint32_t) ib & 31); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13720 | case OP_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13721 | return ia | ib; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13722 | case OP_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13723 | return ia ^ ib; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13724 | case OP_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13725 | return ia & ib; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13726 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13727 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13728 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13729 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13732 | static double b_num_bin_op(enum opcode op, double a, double b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13733 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13734 | * For certain operations, the result is always NaN if either of arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 13735 | * is NaN |
Marko Mikulicic |
0:c0ecb8bf28eb | 13736 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13737 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13738 | case OP_ADD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13739 | case OP_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13740 | case OP_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13741 | case OP_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13742 | case OP_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13743 | if (isnan(a) || isnan(b)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13744 | return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13745 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13746 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13747 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13748 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13751 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13752 | case OP_ADD: /* simple fixed width nodes with no payload */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13753 | return a + b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13754 | case OP_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13755 | return a - b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13756 | case OP_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13757 | if (b == 0 || isnan(b) || isnan(a) || isinf(b) || isinf(a)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13758 | return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13759 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13760 | return (int) a % (int) b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13761 | case OP_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13762 | return a * b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13763 | case OP_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13764 | if (b == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13765 | if (a == 0) return NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13766 | return (!signbit(a) == !signbit(b)) ? INFINITY : -INFINITY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13767 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13768 | return a / b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13769 | case OP_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13770 | case OP_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13771 | case OP_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13772 | case OP_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13773 | case OP_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13774 | case OP_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13775 | return b_int_bin_op(op, a, b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13776 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13777 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13778 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13779 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13780 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13781 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13782 | static int b_bool_bin_op(enum opcode op, double a, double b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13783 | #ifdef V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 13784 | if (isnan(a) || isnan(b)) return op == OP_NE || op == OP_NE_NE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13785 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13786 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13787 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13788 | case OP_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13789 | case OP_EQ_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13790 | return a == b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13791 | case OP_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13792 | case OP_NE_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13793 | return a != b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13794 | case OP_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13795 | return a < b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13796 | case OP_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13797 | return a <= b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13798 | case OP_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13799 | return a > b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13800 | case OP_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13801 | return a >= b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13802 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 13803 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13804 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13805 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13806 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13808 | static bcode_off_t bcode_get_target(char **ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13809 | bcode_off_t target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13810 | (*ops)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13811 | memcpy(&target, *ops, sizeof(target)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13812 | *ops += sizeof(target) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13813 | return target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13816 | struct bcode_registers { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13817 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13818 | * TODO(dfrank): make it contain `struct v7_call_frame_bcode *` |
Marko Mikulicic |
0:c0ecb8bf28eb | 13819 | * and use `bcode_ops` in-place, or probably drop the `bcode_registers` |
Marko Mikulicic |
0:c0ecb8bf28eb | 13820 | * whatsoever |
Marko Mikulicic |
0:c0ecb8bf28eb | 13821 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13822 | struct bcode *bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13823 | char *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13824 | char *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13825 | unsigned int need_inc_ops : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13826 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13828 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13829 | * If returning from function implicitly, then set return value to `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13830 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13831 | * And if function was called as a constructor, then make sure returned |
Marko Mikulicic |
0:c0ecb8bf28eb | 13832 | * value is an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13833 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13834 | static void bcode_adjust_retval(struct v7 *v7, uint8_t is_explicit_return) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13835 | if (!is_explicit_return) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13836 | /* returning implicitly: set return value to `undefined` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13837 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13838 | PUSH(V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13839 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13841 | if (v7->call_stack->is_constructor && !v7_is_object(TOS())) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13842 | /* constructor is going to return non-object: replace it with `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13843 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13844 | PUSH(v7_get_this(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13845 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13846 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13848 | static void bcode_restore_registers(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13849 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13850 | r->bcode = bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13851 | r->ops = bcode->ops.p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13852 | r->end = r->ops + bcode->ops.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13854 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13855 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13856 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13857 | V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13858 | uint8_t type_mask) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13859 | struct v7_call_frame_base *ret = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13861 | while (ret != NULL && !(ret->type_mask & type_mask)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13862 | ret = ret->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13864 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13865 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13868 | static struct v7_call_frame_private *find_call_frame_private(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13869 | return (struct v7_call_frame_private *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13870 | v7, V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13871 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13873 | static struct v7_call_frame_bcode *find_call_frame_bcode(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13874 | return (struct v7_call_frame_bcode *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13875 | v7, V7_CALL_FRAME_MASK_BCODE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13876 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13878 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 13879 | static struct v7_call_frame_cfunc *find_call_frame_cfunc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13880 | return (struct v7_call_frame_cfunc *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 13881 | v7, V7_CALL_FRAME_MASK_CFUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13882 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13883 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 13884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13885 | static struct v7_call_frame_base *create_call_frame(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13886 | size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13887 | struct v7_call_frame_base *call_frame_base = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13889 | call_frame_base = (struct v7_call_frame_base *) calloc(1, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13890 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13891 | /* save previous call frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13892 | call_frame_base->prev = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13894 | /* by default, inherit line_no from the previous frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13895 | if (v7->call_stack != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13896 | call_frame_base->line_no = v7->call_stack->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13897 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13899 | return call_frame_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13900 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13901 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13902 | static void init_call_frame_private(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13903 | struct v7_call_frame_private *call_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13904 | val_t scope) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13905 | /* make a snapshot of the current state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13906 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13907 | struct v7_call_frame_private *cf = find_call_frame_private(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13908 | if (cf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13909 | cf->stack_size = v7->stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13911 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13913 | /* set a type flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13914 | call_frame->base.type_mask |= V7_CALL_FRAME_MASK_PRIVATE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13916 | /* fill the new frame with data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13917 | call_frame->vals.scope = scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13918 | /* `try_stack` will be lazily created in `eval_try_push()`*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13919 | call_frame->vals.try_stack = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13922 | static void init_call_frame_bcode(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13923 | struct v7_call_frame_bcode *call_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13924 | char *prev_bcode_ops, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13925 | val_t this_obj, val_t scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13926 | uint8_t is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13927 | init_call_frame_private(v7, &call_frame->base, scope); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13929 | /* make a snapshot of the current state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13930 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13931 | struct v7_call_frame_bcode *cf = find_call_frame_bcode(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13932 | if (cf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13933 | cf->bcode_ops = prev_bcode_ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13935 | /* remember thrown value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13936 | cf->vals.thrown_error = v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13937 | cf->base.base.is_thrown = v7->is_thrown; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13938 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13939 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13941 | /* set a type flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13942 | call_frame->base.base.type_mask |= V7_CALL_FRAME_MASK_BCODE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13944 | /* fill the new frame with data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13945 | call_frame->bcode = bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13946 | call_frame->vals.this_obj = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13947 | call_frame->base.base.is_constructor = is_constructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13948 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13950 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13951 | * Create new bcode call frame object and fill it with data |
Marko Mikulicic |
0:c0ecb8bf28eb | 13952 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13953 | static void append_call_frame_bcode(struct v7 *v7, char *prev_bcode_ops, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13954 | struct bcode *bcode, val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13955 | val_t scope, uint8_t is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13956 | struct v7_call_frame_bcode *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13957 | (struct v7_call_frame_bcode *) create_call_frame(v7, sizeof(*call_frame)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13959 | init_call_frame_bcode(v7, call_frame, prev_bcode_ops, bcode, this_obj, scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13960 | is_constructor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13961 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13962 | v7->call_stack = &call_frame->base.base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13963 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13964 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13965 | static void append_call_frame_private(struct v7 *v7, val_t scope) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13966 | struct v7_call_frame_private *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13967 | (struct v7_call_frame_private *) create_call_frame(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13968 | sizeof(*call_frame)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13969 | init_call_frame_private(v7, call_frame, scope); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13971 | v7->call_stack = &call_frame->base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13974 | static void append_call_frame_cfunc(struct v7 *v7, val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13975 | v7_cfunction_t *cfunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 13976 | struct v7_call_frame_cfunc *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 13977 | (struct v7_call_frame_cfunc *) create_call_frame(v7, sizeof(*call_frame)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 13978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13979 | /* set a type flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13980 | call_frame->base.type_mask |= V7_CALL_FRAME_MASK_CFUNC; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13982 | /* fill the new frame with data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13983 | call_frame->cfunc = cfunc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13984 | call_frame->vals.this_obj = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13985 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13986 | v7->call_stack = &call_frame->base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 13987 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 13988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 13989 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 13990 | * The caller's bcode object is needed because we have to restore literals |
Marko Mikulicic |
0:c0ecb8bf28eb | 13991 | * and `end` registers. |
Marko Mikulicic |
0:c0ecb8bf28eb | 13992 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13993 | * TODO(mkm): put this state on a return stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 13994 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 13995 | * Caller of bcode_perform_call is responsible for owning `call_frame` |
Marko Mikulicic |
0:c0ecb8bf28eb | 13996 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 13997 | static enum v7_err bcode_perform_call(struct v7 *v7, v7_val_t scope_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13998 | struct v7_js_function *func, |
Marko Mikulicic |
0:c0ecb8bf28eb | 13999 | struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14000 | val_t this_object, char *ops, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14001 | uint8_t is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14002 | /* new scope_frame will inherit from the function's scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14003 | obj_prototype_set(v7, get_object_struct(scope_frame), &func->scope->base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14004 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14005 | /* create new `call_frame` which will replace `v7->call_stack` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14006 | append_call_frame_bcode(v7, r->ops + 1, func->bcode, this_object, scope_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14007 | is_constructor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14009 | bcode_restore_registers(v7, func->bcode, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14010 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14011 | /* adjust `ops` since names were already read from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14012 | r->ops = ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14014 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14015 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14017 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14020 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14021 | * Apply data from the "private" 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. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14025 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14026 | static void apply_frame_private(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14027 | struct v7_call_frame_private *call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14028 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14029 | * Adjust data stack length (restore saved). |
Marko Mikulicic |
0:c0ecb8bf28eb | 14030 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14031 | * If `call_frame` is NULL, it means that the last call frame was just |
Marko Mikulicic |
0:c0ecb8bf28eb | 14032 | * unwound, and hence the data stack size should be 0. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14033 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14034 | size_t stack_size = (call_frame != NULL ? call_frame->stack_size : 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14035 | assert(stack_size <= v7->stack.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14036 | v7->stack.len = stack_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14039 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14040 | * Apply data from the "bcode" call frame, typically after some other frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 14041 | * was just unwound. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14042 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14043 | * The `call_frame` may actually be `NULL`, if the top frame was unwound; but |
Marko Mikulicic |
0:c0ecb8bf28eb | 14044 | * in this case, `r` must be `NULL` too, by design. See inline comment below. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14045 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14046 | static void apply_frame_bcode(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14047 | struct v7_call_frame_bcode *call_frame, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14048 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14049 | if (r != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14050 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14051 | * Note: if `r` is non-NULL, then `call_frame` should be non-NULL as well, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14052 | * by design. If this invariant is violated, it means that |
Marko Mikulicic |
0:c0ecb8bf28eb | 14053 | * `unwind_stack_1level()` is misused. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14054 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14055 | assert(call_frame != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14057 | bcode_restore_registers(v7, call_frame->bcode, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14058 | r->ops = call_frame->bcode_ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14060 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14061 | * restore thrown value if only there's no new thrown value |
Marko Mikulicic |
0:c0ecb8bf28eb | 14062 | * (otherwise, the new one overrides the previous one) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14063 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14064 | if (!v7->is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14065 | v7->vals.thrown_error = call_frame->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14066 | v7->is_thrown = call_frame->base.base.is_thrown; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14068 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14069 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14070 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14071 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14072 | * Unwinds `call_stack` by 1 frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14073 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14074 | * Returns the type of the unwound frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 14075 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14076 | static v7_call_frame_mask_t unwind_stack_1level(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14077 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14078 | v7_call_frame_mask_t type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14079 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14080 | fprintf(stderr, "unwinding stack by 1 level\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14081 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14083 | type_mask = v7->call_stack->type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14085 | /* drop the top frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14086 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14087 | struct v7_call_frame_base *tmp = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14088 | v7->call_stack = v7->call_stack->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14089 | free(tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14090 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14091 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14092 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14093 | * depending on the unwound frame type, apply data from the top call frame(s) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14094 | * which are still alive (if any) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14095 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14097 | if (type_mask & V7_CALL_FRAME_MASK_PRIVATE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14098 | apply_frame_private(v7, find_call_frame_private(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14099 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14100 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14101 | if (type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14102 | apply_frame_bcode(v7, find_call_frame_bcode(v7), r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14103 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14104 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14105 | if (type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14106 | /* Nothing to do here at the moment */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14107 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14109 | return type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14110 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14112 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14113 | * Unwinds local "try stack" (i.e. local-to-current-function stack of nested |
Marko Mikulicic |
0:c0ecb8bf28eb | 14114 | * `try` blocks), looking for local-to-function blocks. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14115 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14116 | * Block types of interest are specified with `wanted_blocks_mask`: it's a |
Marko Mikulicic |
0:c0ecb8bf28eb | 14117 | * bitmask of `enum local_block` values. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14118 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14119 | * Only blocks of specified types will be considered, others will be dropped. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14120 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14121 | * If `restore_stack_size` is non-zero, the `v7->stack.len` will be restored |
Marko Mikulicic |
0:c0ecb8bf28eb | 14122 | * to the value saved when the block was created. This is useful when throwing, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14123 | * since if we throw from the middle of the expression, the stack could have |
Marko Mikulicic |
0:c0ecb8bf28eb | 14124 | * any size. But you probably shouldn't set this flag when breaking and |
Marko Mikulicic |
0:c0ecb8bf28eb | 14125 | * returning, since it may hide real bugs in the opcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14126 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14127 | * Returns id of the block type that control was transferred into, or |
Marko Mikulicic |
0:c0ecb8bf28eb | 14128 | * `LOCAL_BLOCK_NONE` if no appropriate block was found. Note: returned value |
Marko Mikulicic |
0:c0ecb8bf28eb | 14129 | * contains at most 1 block bit; it can't contain multiple bits. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14130 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14131 | static enum local_block unwind_local_blocks_stack( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14132 | struct v7 *v7, struct bcode_registers *r, unsigned int wanted_blocks_mask, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14133 | uint8_t restore_stack_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14134 | val_t arr = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14135 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14136 | enum local_block found_block = LOCAL_BLOCK_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14137 | unsigned long length; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14139 | tmp_stack_push(&tf, &arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14141 | arr = find_call_frame_private(v7)->vals.try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14142 | if (v7_is_array(v7, arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14143 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14144 | * pop latest element from "try stack", loop until we need to transfer |
Marko Mikulicic |
0:c0ecb8bf28eb | 14145 | * control there |
Marko Mikulicic |
0:c0ecb8bf28eb | 14146 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14147 | while ((length = v7_array_length(v7, arr)) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14148 | /* get latest offset from the "try stack" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14149 | int64_t offset = v7_get_double(v7, v7_array_get(v7, arr, length - 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14150 | enum local_block cur_block = LOCAL_BLOCK_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14151 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14152 | /* get id of the current block type */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14153 | switch (LBLOCK_TAG(offset)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14154 | case LBLOCK_TAG_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14155 | cur_block = LOCAL_BLOCK_CATCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14156 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14157 | case LBLOCK_TAG_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14158 | cur_block = LOCAL_BLOCK_FINALLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14159 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14160 | case LBLOCK_TAG_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14161 | cur_block = LOCAL_BLOCK_LOOP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14162 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14163 | case LBLOCK_TAG_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14164 | cur_block = LOCAL_BLOCK_SWITCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14165 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14166 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14167 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14168 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14169 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14170 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14171 | if (cur_block & wanted_blocks_mask) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14172 | /* need to transfer control to this offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14173 | r->ops = r->bcode->ops.p + LBLOCK_OFFSET(offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14174 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14175 | fprintf(stderr, "transferring to block #%d: %u\n", (int) cur_block, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14176 | (unsigned int) LBLOCK_OFFSET(offset)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14177 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14178 | found_block = cur_block; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14179 | /* if needed, restore stack size to the saved value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14180 | if (restore_stack_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14181 | v7->stack.len = LBLOCK_STACK_SIZE(offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14182 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14183 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14184 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14185 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14186 | fprintf(stderr, "skipped block #%d: %u\n", (int) cur_block, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14187 | (unsigned int) LBLOCK_OFFSET(offset)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14188 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14189 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14190 | * since we don't need to control transfer there, just pop |
Marko Mikulicic |
0:c0ecb8bf28eb | 14191 | * it from the "try stack" |
Marko Mikulicic |
0:c0ecb8bf28eb | 14192 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14193 | v7_array_del(v7, arr, length - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14194 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14196 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14198 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14199 | return found_block; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14201 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14202 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14203 | * Perform break, if there is a `finally` block in effect, transfer |
Marko Mikulicic |
0:c0ecb8bf28eb | 14204 | * control there. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14205 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14206 | static void bcode_perform_break(struct v7 *v7, struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14207 | enum local_block found; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14208 | unsigned int mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14209 | v7->is_breaking = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14210 | if (v7->is_continuing) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14211 | mask = LOCAL_BLOCK_LOOP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14212 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14213 | mask = LOCAL_BLOCK_LOOP | LOCAL_BLOCK_SWITCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14214 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14216 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14217 | * Keep unwinding until we find local block of interest. We should not |
Marko Mikulicic |
0:c0ecb8bf28eb | 14218 | * encounter any "function" frames; only "private" frames are allowed. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14219 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14220 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14221 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14222 | * Try to unwind local "try stack", considering only `finally` and `break`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14223 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14224 | found = unwind_local_blocks_stack(v7, r, mask | LOCAL_BLOCK_FINALLY, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14225 | if (found == LOCAL_BLOCK_NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14226 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14227 | * no blocks found: this may happen if only the `break` or `continue` has |
Marko Mikulicic |
0:c0ecb8bf28eb | 14228 | * occurred inside "private" frame. So, unwind this frame, make sure it |
Marko Mikulicic |
0:c0ecb8bf28eb | 14229 | * is indeed a "private" frame, and keep unwinding local blocks. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14230 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14231 | v7_call_frame_mask_t frame_type_mask = unwind_stack_1level(v7, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14232 | assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14233 | (void) frame_type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14234 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14235 | /* found some block to transfer control into, stop unwinding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14236 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14237 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14238 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14239 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14240 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14241 | * upon exit of a finally block we'll reenter here if is_breaking is true. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14242 | * See OP_AFTER_FINALLY. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14243 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14244 | if (found == LOCAL_BLOCK_FINALLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14245 | v7->is_breaking = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14246 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14248 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14249 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14252 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14253 | * Perform return, but if there is a `finally` block in effect, transfer |
Marko Mikulicic |
0:c0ecb8bf28eb | 14254 | * control there. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14255 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14256 | * If `take_retval` is non-zero, value to return will be popped from stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 14257 | * (and saved into `v7->vals.returned_value`), otherwise, it won't ae affected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14258 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14259 | static enum v7_err bcode_perform_return(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14260 | struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14261 | int take_retval) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14262 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14263 | * We should either take retval from the stack, or some value should already |
Marko Mikulicic |
0:c0ecb8bf28eb | 14264 | * de pending to return |
Marko Mikulicic |
0:c0ecb8bf28eb | 14265 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14266 | assert(take_retval || v7->is_returned); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14268 | if (take_retval) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14269 | /* taking return value from stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14270 | v7->vals.returned_value = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14271 | v7->is_returned = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14272 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14273 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14274 | * returning (say, from `finally`) dismisses any errors that are eeing |
Marko Mikulicic |
0:c0ecb8bf28eb | 14275 | * thrown at the moment as well |
Marko Mikulicic |
0:c0ecb8bf28eb | 14276 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14277 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14278 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14279 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14280 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14281 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14282 | * Keep unwinding until we unwound "function" frame, or found some `finally` |
Marko Mikulicic |
0:c0ecb8bf28eb | 14283 | * block. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14284 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14285 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14286 | /* Try to unwind local "try stack", considering only `finally` blocks */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14287 | if (unwind_local_blocks_stack(v7, r, (LOCAL_BLOCK_FINALLY), 0) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 14288 | LOCAL_BLOCK_NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14289 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14290 | * no `finally` blocks were found, so, unwind stack by 1 level, and see |
Marko Mikulicic |
0:c0ecb8bf28eb | 14291 | * if it's a "function" frame. If not, will keep unwinding. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14292 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14293 | if (unwind_stack_1level(v7, r) & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14294 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14295 | * unwound frame is a "function" frame, so, push returned value to |
Marko Mikulicic |
0:c0ecb8bf28eb | 14296 | * stack, and stop unwinding |
Marko Mikulicic |
0:c0ecb8bf28eb | 14297 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14298 | PUSH(v7->vals.returned_value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14299 | v7->is_returned = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14300 | v7->vals.returned_value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14302 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14303 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14304 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14305 | /* found `finally` block, so, stop unwinding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14306 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14307 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14308 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14309 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14310 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14311 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14312 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14313 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14314 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14316 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14317 | * Perform throw inside `eval_bcode()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14318 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14319 | * If `take_thrown_value` is non-zero, value to return will be popped from |
Marko Mikulicic |
0:c0ecb8bf28eb | 14320 | * stack (and saved into `v7->vals.thrown_error`), otherwise, it won't be |
Marko Mikulicic |
0:c0ecb8bf28eb | 14321 | * affected. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14322 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14323 | * Returns `V7_OK` if thrown exception was caught, `V7_EXEC_EXCEPTION` |
Marko Mikulicic |
0:c0ecb8bf28eb | 14324 | * otherwise (in this case, evaluation of current script must be stopped) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14325 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14326 | * When calling this function from `eval_rcode()`, you should wrap this call |
Marko Mikulicic |
0:c0ecb8bf28eb | 14327 | * into the `V7_TRY()` macro. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14328 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14329 | static enum v7_err bcode_perform_throw(struct v7 *v7, struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14330 | int take_thrown_value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14331 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14332 | enum local_block found; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14334 | assert(take_thrown_value || v7->is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14336 | if (take_thrown_value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14337 | v7->vals.thrown_error = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14338 | v7->is_thrown = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14340 | /* Throwing dismisses any pending return values */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14341 | v7->is_returned = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14342 | v7->vals.returned_value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14343 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14345 | while ((found = unwind_local_blocks_stack( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14346 | v7, r, (LOCAL_BLOCK_CATCH | LOCAL_BLOCK_FINALLY), 1)) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 14347 | LOCAL_BLOCK_NONE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14348 | if (v7->call_stack != v7->bottom_call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14349 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14350 | fprintf(stderr, "not at the bottom of the stack, going to unwind..\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14351 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14352 | /* not reached bottom of the stack yet, keep unwinding */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14353 | unwind_stack_1level(v7, r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14354 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14355 | /* reached stack bottom: uncaught exception */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14356 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14357 | fprintf(stderr, "reached stack bottom: uncaught exception\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14358 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14359 | rcode = V7_EXEC_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14360 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14361 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14362 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14364 | if (found == LOCAL_BLOCK_CATCH) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14365 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14366 | * we're going to enter `catch` block, so, populate TOS with the thrown |
Marko Mikulicic |
0:c0ecb8bf28eb | 14367 | * value, and clear it in v7 context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14368 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14369 | PUSH(v7->vals.thrown_error); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14370 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14371 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14372 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14374 | /* `ops` already points to the needed instruction, no need to increment it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14375 | r->need_inc_ops = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14377 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14378 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14380 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14381 | * Throws reference error from `eval_bcode()`. Always wrap a call to this |
Marko Mikulicic |
0:c0ecb8bf28eb | 14382 | * function into `V7_TRY()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14383 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14384 | static enum v7_err bcode_throw_reference_error(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14385 | struct bcode_registers *r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14386 | val_t var_name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14387 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14388 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14389 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14391 | assert(v7_is_string(var_name)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14392 | s = v7_get_string(v7, &var_name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14394 | rcode = v7_throwf(v7, REFERENCE_ERROR, "[%.*s] is not defined", |
Marko Mikulicic |
0:c0ecb8bf28eb | 14395 | (int) name_len, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14396 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14397 | return bcode_perform_throw(v7, r, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14398 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14400 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14401 | * Takes a half-done function (either from literal table or deserialized from |
Marko Mikulicic |
0:c0ecb8bf28eb | 14402 | * `ops` inlined data), and returns a ready-to-use function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14403 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14404 | * The actual behaviour depends on whether the half-done function has |
Marko Mikulicic |
0:c0ecb8bf28eb | 14405 | * `prototype` defined. If there's no prototype (i.e. it's `undefined`), then |
Marko Mikulicic |
0:c0ecb8bf28eb | 14406 | * the new function is created, with bcode from a given one. If, however, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14407 | * the prototype is defined, it means that the function was just deserialized |
Marko Mikulicic |
0:c0ecb8bf28eb | 14408 | * from `ops`, so we only need to set `scope` on it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14409 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 14410 | * Assumes `func` is owned by the caller. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14411 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14412 | static val_t bcode_instantiate_function(struct v7 *v7, val_t func) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14413 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14414 | struct v7_generic_object *scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14415 | struct v7_js_function *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14416 | assert(is_js_function(func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14417 | f = get_js_function_struct(func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14419 | scope = get_generic_object_struct(get_scope(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14421 | if (v7_is_undefined(v7_get(v7, func, "prototype", 9))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14422 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14423 | * Function's `prototype` is `undefined`: it means that the function is |
Marko Mikulicic |
0:c0ecb8bf28eb | 14424 | * created by the compiler and is stored in the literal table. We have to |
Marko Mikulicic |
0:c0ecb8bf28eb | 14425 | * create completely new function |
Marko Mikulicic |
0:c0ecb8bf28eb | 14426 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14427 | struct v7_js_function *rf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14429 | res = mk_js_function(v7, scope, v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14431 | /* Copy and retain bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14432 | rf = get_js_function_struct(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14433 | rf->bcode = f->bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14434 | retain_bcode(v7, rf->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14435 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14436 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14437 | * Function's `prototype` is NOT `undefined`: it means that the function is |
Marko Mikulicic |
0:c0ecb8bf28eb | 14438 | * deserialized from inline `ops` data, and we just need to set scope on |
Marko Mikulicic |
0:c0ecb8bf28eb | 14439 | * it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14440 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14441 | res = func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14442 | f->scope = scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14445 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14448 | /** |
Marko Mikulicic |
0:c0ecb8bf28eb | 14449 | * Call C function `func` with given `this_object` and array of arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 14450 | * `args`. `func` should be a C function pointer, not C function object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14451 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14452 | static enum v7_err call_cfunction(struct v7 *v7, val_t func, val_t this_object, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14453 | val_t args, uint8_t is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14454 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14455 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14456 | uint8_t saved_inhibit_gc = v7->inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14457 | val_t saved_arguments = v7->vals.arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14458 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14459 | v7_cfunction_t *cfunc = get_cfunction_ptr(v7, func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14461 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14463 | tmp_stack_push(&tf, &saved_arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14465 | append_call_frame_cfunc(v7, this_object, cfunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14467 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14468 | * prepare cfunction environment |
Marko Mikulicic |
0:c0ecb8bf28eb | 14469 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14470 | v7->inhibit_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14471 | v7->vals.arguments = args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14473 | /* call C function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14474 | rcode = cfunc(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14475 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14476 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14477 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14478 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14479 | if (is_constructor && !v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14480 | /* constructor returned non-object: replace it with `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14481 | *res = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14482 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14484 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14485 | v7->vals.arguments = saved_arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14486 | v7->inhibit_gc = saved_inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14488 | unwind_stack_1level(v7, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14490 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14491 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14492 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14494 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14495 | * Evaluate `OP_TRY_PUSH_CATCH` or `OP_TRY_PUSH_FINALLY`: Take an offset (from |
Marko Mikulicic |
0:c0ecb8bf28eb | 14496 | * the parameter of opcode) and push it onto "try stack" |
Marko Mikulicic |
0:c0ecb8bf28eb | 14497 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14498 | static void eval_try_push(struct v7 *v7, enum opcode op, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14499 | struct bcode_registers *r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14500 | val_t arr = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14501 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14502 | bcode_off_t target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14503 | int64_t offset_tag = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14505 | tmp_stack_push(&tf, &arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14507 | /* make sure "try stack" array exists */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14508 | arr = find_call_frame_private(v7)->vals.try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14509 | if (!v7_is_array(v7, arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14510 | arr = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14511 | find_call_frame_private(v7)->vals.try_stack = arr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14512 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14513 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14514 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14515 | * push the target address at the end of the "try stack" array |
Marko Mikulicic |
0:c0ecb8bf28eb | 14516 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14517 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14518 | case OP_TRY_PUSH_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14519 | offset_tag = LBLOCK_TAG_CATCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14520 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14521 | case OP_TRY_PUSH_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14522 | offset_tag = LBLOCK_TAG_FINALLY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14523 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14524 | case OP_TRY_PUSH_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14525 | offset_tag = LBLOCK_TAG_LOOP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14526 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14527 | case OP_TRY_PUSH_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14528 | offset_tag = LBLOCK_TAG_SWITCH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14529 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14530 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14531 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14532 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14533 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14534 | target = bcode_get_target(&r->ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14535 | v7_array_push(v7, arr, v7_mk_number(v7, LBLOCK_ITEM_CREATE(target, offset_tag, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14536 | v7->stack.len))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14537 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14538 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14539 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14540 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14541 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14542 | * Evaluate `OP_TRY_POP`: just pop latest item from "try stack", ignoring it |
Marko Mikulicic |
0:c0ecb8bf28eb | 14543 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14544 | static enum v7_err eval_try_pop(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14545 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14546 | val_t arr = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14547 | unsigned long length; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14548 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14549 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14550 | tmp_stack_push(&tf, &arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14552 | /* get "try stack" array, which must be defined and must not be emtpy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14553 | arr = find_call_frame_private(v7)->vals.try_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14554 | if (!v7_is_array(v7, arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14555 | rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is not an array"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14556 | V7_TRY(V7_INTERNAL_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14557 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14558 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14559 | length = v7_array_length(v7, arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14560 | if (length == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14561 | rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is empty"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14562 | V7_TRY(V7_INTERNAL_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14563 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14565 | /* delete the latest element of this array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14566 | v7_array_del(v7, arr, length - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14567 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14568 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14569 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14570 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14571 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14572 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14573 | static void own_bcode(struct v7 *v7, struct bcode *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14574 | mbuf_append(&v7->act_bcodes, &p, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14575 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14576 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14577 | static void disown_bcode(struct v7 *v7, struct bcode *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14578 | #ifndef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 14579 | struct bcode **vp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 14580 | (struct bcode **) (v7->act_bcodes.buf + v7->act_bcodes.len - sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14582 | /* given `p` should be the last item */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14583 | assert(*vp == p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14584 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14585 | v7->act_bcodes.len -= sizeof(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14586 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14587 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14588 | /* Keeps track of last evaluated bcodes in order to improve error reporting */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14589 | static void push_bcode_history(struct v7 *v7, enum opcode op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14590 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14592 | if (op == OP_CHECK_CALL || op == OP_CALL || op == OP_NEW) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14594 | for (i = ARRAY_SIZE(v7->last_ops) - 1; i > 0; i--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14595 | v7->last_ops[i] = v7->last_ops[i - 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14596 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14597 | v7->last_ops[0] = op; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14598 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14599 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14600 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 14601 | static void reset_last_name(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14602 | v7->vals.last_name[0] = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14603 | v7->vals.last_name[1] = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14604 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14605 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 14606 | static void reset_last_name(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14607 | /* should be inlined out */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14608 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14609 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14610 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14612 | static void prop_iter_ctx_dtor(struct v7 *v7, void *ud) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14613 | struct prop_iter_ctx *ctx = (struct prop_iter_ctx *) ud; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14614 | v7_destruct_prop_iter_ctx(v7, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14615 | free(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14616 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14618 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14619 | * Evaluates given `bcode`. If `reset_line_no` is non-zero, the line number |
Marko Mikulicic |
0:c0ecb8bf28eb | 14620 | * is initially reset to 1; otherwise, it is inherited from the previous call |
Marko Mikulicic |
0:c0ecb8bf28eb | 14621 | * frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14622 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14623 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 14624 | V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14625 | val_t this_object, uint8_t reset_line_no, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14626 | val_t *_res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14627 | struct bcode_registers r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14628 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14629 | struct v7_call_frame_base *saved_bottom_call_frame = v7->bottom_call_frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14630 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14631 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14632 | * Dummy variable just to enforce that `BTRY()` macro is used only inside the |
Marko Mikulicic |
0:c0ecb8bf28eb | 14633 | * `eval_bcode()` function |
Marko Mikulicic |
0:c0ecb8bf28eb | 14634 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14635 | uint8_t _you_should_use_BTRY_in_eval_bcode_only = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14637 | char buf[512]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14638 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14639 | val_t res = V7_UNDEFINED, v1 = V7_UNDEFINED, v2 = V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14640 | v3 = V7_UNDEFINED, v4 = V7_UNDEFINED, scope_frame = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14641 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14643 | append_call_frame_bcode(v7, NULL, bcode, this_object, get_scope(v7), 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14645 | if (reset_line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14646 | v7->call_stack->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14647 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14649 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14650 | * Set current call stack as the "bottom" call stack, so that bcode evaluator |
Marko Mikulicic |
0:c0ecb8bf28eb | 14651 | * will exit when it reaches this "bottom" |
Marko Mikulicic |
0:c0ecb8bf28eb | 14652 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14653 | v7->bottom_call_frame = v7->call_stack; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14655 | bcode_restore_registers(v7, bcode, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14656 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14657 | tmp_stack_push(&tf, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14658 | tmp_stack_push(&tf, &v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14659 | tmp_stack_push(&tf, &v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14660 | tmp_stack_push(&tf, &v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14661 | tmp_stack_push(&tf, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14662 | tmp_stack_push(&tf, &scope_frame); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14664 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14665 | * populate local variables on current scope, making them undeletable |
Marko Mikulicic |
0:c0ecb8bf28eb | 14666 | * (since they're defined with `var`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14667 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14668 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14669 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14670 | for (i = 0; i < bcode->names_cnt; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14671 | r.ops = bcode_next_name_v(v7, bcode, r.ops, &v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14673 | /* set undeletable property on current scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14674 | V7_TRY(def_property_v(v7, get_scope(v7), v1, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14675 | V7_UNDEFINED, 1 /*as_assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14679 | restart: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14680 | while (r.ops < r.end && rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14681 | enum opcode op = (enum opcode) * r.ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14683 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 14684 | if ((uint8_t) op >= _OP_LINE_NO) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14685 | unsigned char buf[sizeof(size_t)]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14686 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14687 | size_t max_llen = sizeof(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14689 | /* ASAN doesn't like out of bound reads */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14690 | if (r.ops + max_llen > r.end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14691 | max_llen = r.end - r.ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14692 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14694 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14695 | * before we decode varint, we'll have to swap MSB and LSB, but we can't |
Marko Mikulicic |
0:c0ecb8bf28eb | 14696 | * do it in place since we're decoding from constant memory, so, we also |
Marko Mikulicic |
0:c0ecb8bf28eb | 14697 | * have to copy the data to the temp buffer first. 4 bytes should be |
Marko Mikulicic |
0:c0ecb8bf28eb | 14698 | * enough for everyone's line number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 14699 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14700 | memcpy(buf, r.ops, max_llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14701 | buf[0] = msb_lsb_swap(buf[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14702 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14703 | v7->call_stack->line_no = decode_varint(buf, &len) >> 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14704 | assert((size_t) len <= sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14705 | r.ops += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14707 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14708 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14709 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14711 | push_bcode_history(v7, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14713 | if (v7->need_gc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14714 | if (maybe_gc(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14715 | v7->need_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14716 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14717 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14719 | r.need_inc_ops = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14720 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 14721 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14722 | char *dops = r.ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14723 | fprintf(stderr, "eval "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14724 | dump_op(v7, stderr, r.bcode, &dops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14725 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14726 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14727 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14728 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14729 | case OP_DROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14730 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14731 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14732 | case OP_DUP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14733 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14734 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14735 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14736 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14737 | case OP_2DUP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14738 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14739 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14740 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14741 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14742 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14743 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14744 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14745 | case OP_SWAP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14746 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14747 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14748 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14749 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14750 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14751 | case OP_STASH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14752 | assert(!v7->is_stashed); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14753 | v7->vals.stash = TOS(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14754 | v7->is_stashed = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14755 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14756 | case OP_UNSTASH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14757 | assert(v7->is_stashed); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14758 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14759 | PUSH(v7->vals.stash); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14760 | v7->vals.stash = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14761 | v7->is_stashed = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14762 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14764 | case OP_SWAP_DROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14765 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14766 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14767 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14768 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14769 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14770 | case OP_PUSH_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14771 | PUSH(V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14772 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14773 | case OP_PUSH_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14774 | PUSH(V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14775 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14776 | case OP_PUSH_THIS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14777 | PUSH(v7_get_this(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14778 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14779 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14780 | case OP_PUSH_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14781 | PUSH(v7_mk_boolean(v7, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14782 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14783 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14784 | case OP_PUSH_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14785 | PUSH(v7_mk_boolean(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14786 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14787 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14788 | case OP_PUSH_ZERO: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14789 | PUSH(v7_mk_number(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14790 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14791 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14792 | case OP_PUSH_ONE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14793 | PUSH(v7_mk_number(v7, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14794 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14795 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14796 | case OP_PUSH_LIT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14797 | PUSH(bcode_decode_lit(v7, r.bcode, &r.ops)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14798 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 14799 | /* name tracking */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14800 | if (!v7_is_string(TOS())) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14801 | reset_last_name(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14803 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 14804 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14805 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14806 | case OP_LOGICAL_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14807 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14808 | PUSH(v7_mk_boolean(v7, !v7_is_truthy(v7, v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14809 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14810 | case OP_NOT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14811 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14812 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14813 | PUSH(v7_mk_number(v7, ~(int32_t) v7_get_double(v7, v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14814 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14815 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14816 | case OP_NEG: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14817 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14818 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14819 | PUSH(v7_mk_number(v7, -v7_get_double(v7, v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14820 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14822 | case OP_POS: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14823 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14824 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14825 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14826 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14828 | case OP_ADD: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14829 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14830 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14831 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14832 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14833 | * If either operand is an object, convert both of them to primitives |
Marko Mikulicic |
0:c0ecb8bf28eb | 14834 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14835 | if (v7_is_object(v1) || v7_is_object(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14836 | BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_AUTO, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14837 | BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_AUTO, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14838 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14840 | if (v7_is_string(v1) || v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14841 | /* Convert both operands to strings, and concatenate */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14843 | BTRY(primitive_to_str(v7, v1, &v1, NULL, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14844 | BTRY(primitive_to_str(v7, v2, &v2, NULL, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14846 | PUSH(s_concat(v7, v1, v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14847 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14848 | /* Convert both operands to numbers, and sum */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14850 | BTRY(primitive_to_number(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14851 | BTRY(primitive_to_number(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14853 | PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14854 | v7_get_double(v7, v2)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14855 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14856 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14857 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14858 | case OP_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14859 | case OP_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14860 | case OP_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14861 | case OP_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14862 | case OP_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14863 | case OP_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14864 | case OP_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14865 | case OP_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14866 | case OP_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14867 | case OP_AND: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14868 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14869 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14871 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14872 | BTRY(to_number_v(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14874 | PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14875 | v7_get_double(v7, v2)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14876 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14878 | case OP_EQ_EQ: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14879 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14880 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14881 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14882 | res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14883 | } else if (v1 == v2 && v1 == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14884 | res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14885 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14886 | res = v7_mk_boolean(v7, v1 == v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14887 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14888 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14889 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14890 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14891 | case OP_NE_NE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14892 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14893 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14894 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14895 | res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) != 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14896 | } else if (v1 == v2 && v1 == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14897 | res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14898 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14899 | res = v7_mk_boolean(v7, v1 != v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14900 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14901 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14902 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14903 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14904 | case OP_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14905 | case OP_NE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14906 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14907 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14908 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 14909 | * TODO(dfrank) : it's not really correct. Fix it accordingly to |
Marko Mikulicic |
0:c0ecb8bf28eb | 14910 | * the p. 4.9 of The Definitive Guide (page 71) |
Marko Mikulicic |
0:c0ecb8bf28eb | 14911 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14912 | if (((v7_is_object(v1) || v7_is_object(v2)) && v1 == v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14913 | res = v7_mk_boolean(v7, op == OP_EQ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14914 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14915 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14916 | } else if (v7_is_undefined(v1) || v7_is_null(v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14917 | res = v7_mk_boolean( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14918 | v7, (op != OP_EQ) ^ (v7_is_undefined(v2) || v7_is_null(v2))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14919 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14920 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14921 | } else if (v7_is_undefined(v2) || v7_is_null(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14922 | res = v7_mk_boolean( |
Marko Mikulicic |
0:c0ecb8bf28eb | 14923 | v7, (op != OP_EQ) ^ (v7_is_undefined(v1) || v7_is_null(v1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14924 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14925 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14926 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14928 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14929 | int cmp = s_cmp(v7, v1, v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14930 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14931 | case OP_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14932 | res = v7_mk_boolean(v7, cmp == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14933 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14934 | case OP_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14935 | res = v7_mk_boolean(v7, cmp != 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14936 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14937 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14938 | /* should never be here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14939 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14940 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14941 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14942 | /* Convert both operands to numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14944 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14945 | BTRY(to_number_v(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14946 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14947 | res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14948 | v7_get_double(v7, v2))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14949 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14950 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14951 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14952 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14953 | case OP_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14954 | case OP_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14955 | case OP_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14956 | case OP_GE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14957 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14958 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14959 | BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_NUMBER, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14960 | BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_NUMBER, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14961 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14962 | if (v7_is_string(v1) && v7_is_string(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14963 | int cmp = s_cmp(v7, v1, v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14964 | switch (op) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14965 | case OP_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14966 | res = v7_mk_boolean(v7, cmp < 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14967 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14968 | case OP_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14969 | res = v7_mk_boolean(v7, cmp <= 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14970 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14971 | case OP_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14972 | res = v7_mk_boolean(v7, cmp > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14973 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14974 | case OP_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14975 | res = v7_mk_boolean(v7, cmp >= 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14976 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14977 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 14978 | /* should never be here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14979 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14980 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14981 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14982 | /* Convert both operands to numbers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 14983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14984 | BTRY(to_number_v(v7, v1, &v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14985 | BTRY(to_number_v(v7, v2, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 14987 | res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 14988 | v7_get_double(v7, v2))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14989 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14990 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14991 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 14992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 14993 | case OP_INSTANCEOF: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14994 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14995 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14996 | if (!v7_is_callable(v7, v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 14997 | BTRY(v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 14998 | "Expecting a function in instanceof check")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 14999 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15000 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15001 | PUSH(v7_mk_boolean( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15002 | v7, is_prototype_of(v7, v1, v7_get(v7, v2, "prototype", 9)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15003 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15004 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15005 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15006 | case OP_TYPEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15007 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15008 | switch (val_type(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15009 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15010 | res = v7_mk_string(v7, "number", 6, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15011 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15012 | case V7_TYPE_STRING: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15013 | res = v7_mk_string(v7, "string", 6, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15014 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15015 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15016 | res = v7_mk_string(v7, "boolean", 7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15017 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15018 | case V7_TYPE_FUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15019 | case V7_TYPE_CFUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15020 | case V7_TYPE_CFUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15021 | res = v7_mk_string(v7, "function", 8, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15022 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15023 | case V7_TYPE_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15024 | res = v7_mk_string(v7, "undefined", 9, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15025 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15026 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15027 | res = v7_mk_string(v7, "object", 6, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15028 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15029 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15030 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15031 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15032 | case OP_IN: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15033 | struct v7_property *prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15034 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15035 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15036 | BTRY(to_string(v7, v1, NULL, buf, sizeof(buf), NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15037 | prop = v7_get_property(v7, v2, buf, ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15038 | PUSH(v7_mk_boolean(v7, prop != NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15039 | } break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15040 | case OP_GET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15041 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15042 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15043 | BTRY(v7_get_throwing_v(v7, v1, v2, &v3)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15044 | PUSH(v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15045 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15046 | v7->vals.last_name[1] = v7->vals.last_name[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15047 | v7->vals.last_name[0] = v2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15048 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15049 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15050 | case OP_SET: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15051 | v3 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15052 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15053 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15054 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15055 | /* convert name to string, if it's not already */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15056 | BTRY(to_string(v7, v2, &v2, NULL, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15058 | /* set value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15059 | BTRY(set_property_v(v7, v1, v2, v3, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15061 | PUSH(v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15062 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15063 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15064 | case OP_GET_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15065 | case OP_SAFE_GET_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15066 | struct v7_property *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15067 | assert(r.ops < r.end - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15068 | v1 = bcode_decode_lit(v7, r.bcode, &r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15069 | BTRY(v7_get_property_v(v7, get_scope(v7), v1, &p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15070 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15071 | if (op == OP_SAFE_GET_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15072 | PUSH(V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15073 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15074 | /* variable does not exist: Reference Error */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15075 | V7_TRY(bcode_throw_reference_error(v7, &r, v1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15076 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15078 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15079 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15080 | BTRY(v7_property_value(v7, get_scope(v7), p, &v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15081 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15082 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15083 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15084 | v7->vals.last_name[0] = v1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15085 | v7->vals.last_name[1] = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15086 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15087 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15089 | case OP_SET_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15090 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15091 | v3 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15092 | v2 = bcode_decode_lit(v7, r.bcode, &r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15093 | v1 = get_scope(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15095 | BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15096 | prop = v7_get_property(v7, v1, buf, strlen(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15097 | if (prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15098 | /* Property already exists: update its value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15099 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15100 | * TODO(dfrank): currently we can't use `def_property_v()` here, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15101 | * because if the property was already found somewhere in the |
Marko Mikulicic |
0:c0ecb8bf28eb | 15102 | * prototype chain, then it should be updated, instead of creating a |
Marko Mikulicic |
0:c0ecb8bf28eb | 15103 | * new one on the top of the scope. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15104 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15105 | * Probably we need to make `def_property_v()` more generic and |
Marko Mikulicic |
0:c0ecb8bf28eb | 15106 | * use it here; or split `def_property_v()` into smaller pieces and |
Marko Mikulicic |
0:c0ecb8bf28eb | 15107 | * use one of them here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15108 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15109 | if (!(prop->attributes & V7_PROPERTY_NON_WRITABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15110 | prop->value = v3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15112 | } else if (!r.bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15113 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15114 | * Property does not exist: since we're not in strict mode, let's |
Marko Mikulicic |
0:c0ecb8bf28eb | 15115 | * create new property at Global Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15116 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15117 | BTRY(set_property_v(v7, v7_get_global(v7), v2, v3, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15118 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15119 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15120 | * In strict mode, throw reference error instead of polluting Global |
Marko Mikulicic |
0:c0ecb8bf28eb | 15121 | * Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15122 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15123 | V7_TRY(bcode_throw_reference_error(v7, &r, v2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15124 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15125 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15126 | PUSH(v3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15127 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15128 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15129 | case OP_JMP: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15130 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15131 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15132 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15133 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15134 | case OP_JMP_FALSE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15135 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15136 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15137 | if (!v7_is_truthy(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15138 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15139 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15140 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15142 | case OP_JMP_TRUE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15143 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15144 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15145 | if (v7_is_truthy(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15146 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15147 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15148 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15149 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15150 | case OP_JMP_TRUE_DROP: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15151 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15152 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15153 | if (v7_is_truthy(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15154 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15155 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15156 | POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15157 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15158 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15159 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15160 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15161 | case OP_JMP_IF_CONTINUE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15162 | bcode_off_t target = bcode_get_target(&r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15163 | if (v7->is_continuing) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15164 | r.ops = r.bcode->ops.p + target - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15165 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15166 | v7->is_continuing = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15167 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15168 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15169 | case OP_CREATE_OBJ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15170 | PUSH(v7_mk_object(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15171 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15172 | case OP_CREATE_ARR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15173 | PUSH(v7_mk_array(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15174 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15175 | case OP_PUSH_PROP_ITER_CTX: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15176 | struct prop_iter_ctx *ctx = |
Marko Mikulicic |
0:c0ecb8bf28eb | 15177 | (struct prop_iter_ctx *) calloc(1, sizeof(*ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15178 | BTRY(init_prop_iter_ctx(v7, TOS(), 1, ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15179 | v1 = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15180 | v7_set_user_data(v7, v1, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15181 | v7_set_destructor_cb(v7, v1, prop_iter_ctx_dtor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15182 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15183 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15184 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15185 | case OP_NEXT_PROP: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15186 | struct prop_iter_ctx *ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15187 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15188 | v1 = POP(); /* ctx */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15189 | v2 = POP(); /* object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15191 | ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15192 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15193 | if (v7_is_object(v2)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15194 | v7_prop_attr_t attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15195 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15196 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15197 | /* iterate properties until we find a non-hidden enumerable one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15198 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15199 | BTRY(next_prop(v7, ctx, &res, NULL, &attrs, &ok)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15200 | } while (ok && (attrs & (_V7_PROPERTY_HIDDEN | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15201 | V7_PROPERTY_NON_ENUMERABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15203 | if (!ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15204 | /* no more properties in this object: proceed to the prototype */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15205 | v2 = v7_get_proto(v7, v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15206 | if (get_generic_object_struct(v2) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15207 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15208 | * the prototype is a generic object, so, init the context for |
Marko Mikulicic |
0:c0ecb8bf28eb | 15209 | * props iteration |
Marko Mikulicic |
0:c0ecb8bf28eb | 15210 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15211 | v7_destruct_prop_iter_ctx(v7, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15212 | BTRY(init_prop_iter_ctx(v7, v2, 1, ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15213 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15214 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15215 | * we can't iterate the prototype's props, so, just stop |
Marko Mikulicic |
0:c0ecb8bf28eb | 15216 | * iteration. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15217 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15218 | ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15219 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15220 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15221 | } while (!ok && ctx != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15222 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15223 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15224 | * Not an object: reset the context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15225 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15226 | ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15227 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15229 | if (ctx == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15230 | PUSH(v7_mk_boolean(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15231 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15232 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15233 | * We could leave the context unfreed, and let the |
Marko Mikulicic |
0:c0ecb8bf28eb | 15234 | * `prop_iter_ctx_dtor()` free it when the v1 will be GC-d, but |
Marko Mikulicic |
0:c0ecb8bf28eb | 15235 | * let's do that earlier. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15236 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15237 | ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15238 | v7_destruct_prop_iter_ctx(v7, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15239 | free(ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15240 | v7_set_user_data(v7, v1, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15241 | v7_set_destructor_cb(v7, v1, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15242 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15243 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15244 | PUSH(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15245 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15246 | PUSH(v7_mk_boolean(v7, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15247 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15248 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15250 | case OP_FUNC_LIT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15251 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15252 | v2 = bcode_instantiate_function(v7, v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15253 | PUSH(v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15254 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15255 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15256 | case OP_CHECK_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15257 | v1 = TOS(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15258 | if (!v7_is_callable(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15259 | int arity = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15260 | enum v7_err ignore; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15261 | /* tried to call non-function object: throw a TypeError */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15263 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15264 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15265 | * try to provide some useful context for the error message |
Marko Mikulicic |
0:c0ecb8bf28eb | 15266 | * using a good-enough heuristics |
Marko Mikulicic |
0:c0ecb8bf28eb | 15267 | * but defer actual throw when process the incriminated call |
Marko Mikulicic |
0:c0ecb8bf28eb | 15268 | * in order to evaluate the arguments as required by the spec. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15269 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15270 | if (v7->last_ops[0] == OP_GET_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15271 | arity = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15272 | } else if (v7->last_ops[0] == OP_GET && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15273 | v7->last_ops[1] == OP_PUSH_LIT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15274 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15275 | * OP_PUSH_LIT is used to both push property names for OP_GET |
Marko Mikulicic |
0:c0ecb8bf28eb | 15276 | * and for pushing actual literals. During PUSH_LIT push lit |
Marko Mikulicic |
0:c0ecb8bf28eb | 15277 | * evaluation we reset the last name variable in case the literal |
Marko Mikulicic |
0:c0ecb8bf28eb | 15278 | * is not a string, such as in `[].foo()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15279 | * Unfortunately it doesn't handle `"foo".bar()`; could be |
Marko Mikulicic |
0:c0ecb8bf28eb | 15280 | * solved by adding another bytecode for property literals but |
Marko Mikulicic |
0:c0ecb8bf28eb | 15281 | * probably it doesn't matter much. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15282 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15283 | if (v7_is_undefined(v7->vals.last_name[1])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15284 | arity = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15285 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15286 | arity = 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15287 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15288 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15289 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15290 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15291 | switch (arity) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15292 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15293 | ignore = v7_throwf(v7, TYPE_ERROR, "value is not a function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15294 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15295 | #ifndef V7_DISABLE_CALL_ERROR_CONTEXT |
Marko Mikulicic |
0:c0ecb8bf28eb | 15296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15297 | case 1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15298 | ignore = v7_throwf(v7, TYPE_ERROR, "%s is not a function", |
Marko Mikulicic |
0:c0ecb8bf28eb | 15299 | v7_get_cstring(v7, &v7->vals.last_name[0])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15300 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15301 | case 2: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15302 | ignore = v7_throwf(v7, TYPE_ERROR, "%s.%s is not a function", |
Marko Mikulicic |
0:c0ecb8bf28eb | 15303 | v7_get_cstring(v7, &v7->vals.last_name[1]), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15304 | v7_get_cstring(v7, &v7->vals.last_name[0])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15305 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15306 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15307 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15309 | v7->vals.call_check_ex = v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15310 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15311 | (void) ignore; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15313 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15314 | case OP_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15315 | case OP_NEW: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15316 | /* Naive implementation pending stack frame redesign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15317 | int args = (int) *(++r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15318 | uint8_t is_constructor = (op == OP_NEW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15320 | if (SP() < (args + 1 /*func*/ + 1 /*this*/)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15321 | BTRY(v7_throwf(v7, INTERNAL_ERROR, "stack underflow")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15322 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15323 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15324 | v2 = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15325 | while (args > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15326 | BTRY(v7_array_set_throwing(v7, v2, --args, POP(), NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15327 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15328 | /* pop function to call */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15329 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15331 | /* pop `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15332 | v3 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15334 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15335 | * adjust `this` if the function is called with the constructor |
Marko Mikulicic |
0:c0ecb8bf28eb | 15336 | * invocation pattern |
Marko Mikulicic |
0:c0ecb8bf28eb | 15337 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15338 | if (is_constructor) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15339 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15340 | * The function is invoked as a constructor: we ignore `this` |
Marko Mikulicic |
0:c0ecb8bf28eb | 15341 | * value popped from stack, create new object and set prototype. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15342 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15344 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15345 | * get "prototype" property from the constructor function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15346 | * and make sure it's an object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15347 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15348 | v4 = v7_get(v7, v1 /*func*/, "prototype", 9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15349 | if (!v7_is_object(v4)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15350 | /* TODO(dfrank): box primitive value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15351 | BTRY(v7_throwf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15352 | v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15353 | "Cannot set a primitive value as object prototype")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15354 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15355 | } else if (is_cfunction_lite(v4)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15356 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15357 | * TODO(dfrank): maybe add support for a cfunction pointer to be |
Marko Mikulicic |
0:c0ecb8bf28eb | 15358 | * a prototype |
Marko Mikulicic |
0:c0ecb8bf28eb | 15359 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15360 | BTRY(v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15361 | "Not implemented: cfunction as a prototype")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15362 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15365 | /* create an object with given prototype */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15366 | v3 = mk_object(v7, v4 /*prototype*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15367 | v4 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15368 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15370 | if (!v7_is_callable(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15371 | /* tried to call non-function object: throw a TypeError */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15372 | BTRY(v7_throw(v7, v7->vals.call_check_ex)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15373 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15374 | } else if (is_cfunction_lite(v1) || is_cfunction_obj(v7, v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15375 | /* call cfunction */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15377 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15378 | * In "function invocation pattern", the `this` value popped from |
Marko Mikulicic |
0:c0ecb8bf28eb | 15379 | * stack is an `undefined`. And in non-strict mode, we should change |
Marko Mikulicic |
0:c0ecb8bf28eb | 15380 | * it to global object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15381 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15382 | if (!is_constructor && !r.bcode->strict_mode && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15383 | v7_is_undefined(v3)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15384 | v3 = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15385 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15387 | BTRY(call_cfunction(v7, v1 /*func*/, v3 /*this*/, v2 /*args*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15388 | is_constructor, &v4)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15390 | /* push value returned from C function to bcode stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15391 | PUSH(v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15393 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15394 | char *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15395 | struct v7_js_function *func = get_js_function_struct(v1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15397 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15398 | * In "function invocation pattern", the `this` value popped from |
Marko Mikulicic |
0:c0ecb8bf28eb | 15399 | * stack is an `undefined`. And in non-strict mode, we should change |
Marko Mikulicic |
0:c0ecb8bf28eb | 15400 | * it to global object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15401 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15402 | if (!is_constructor && !func->bcode->strict_mode && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15403 | v7_is_undefined(v3)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15404 | v3 = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15405 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15406 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15407 | scope_frame = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15409 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15410 | * Before actual opcodes, `ops` contains one or more |
Marko Mikulicic |
0:c0ecb8bf28eb | 15411 | * null-terminated strings: first of all, the function name (if the |
Marko Mikulicic |
0:c0ecb8bf28eb | 15412 | * function is anonymous, it's an empty string). |
Marko Mikulicic |
0:c0ecb8bf28eb | 15413 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15414 | * Then, argument names follow. We know number of arguments, so, we |
Marko Mikulicic |
0:c0ecb8bf28eb | 15415 | * know how many names to take. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15416 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15417 | * And then, local variable names follow. We know total number of |
Marko Mikulicic |
0:c0ecb8bf28eb | 15418 | * strings (`names_cnt`), so, again, we know how many names to |
Marko Mikulicic |
0:c0ecb8bf28eb | 15419 | * take. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15420 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15422 | ops = func->bcode->ops.p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15424 | /* populate function itself */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15425 | ops = bcode_next_name_v(v7, func->bcode, ops, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15426 | BTRY(def_property_v(v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15427 | v1, 0 /*not assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15429 | /* populate arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15430 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15431 | int arg_num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15432 | for (arg_num = 0; arg_num < func->bcode->args_cnt; ++arg_num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15433 | ops = bcode_next_name_v(v7, func->bcode, ops, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15434 | BTRY(def_property_v( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15435 | v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15436 | v7_array_get(v7, v2, arg_num), 0 /*not assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15437 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15438 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15440 | /* populate `arguments` object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15442 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15443 | * TODO(dfrank): it's actually much more complicated than that: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15444 | * it's not an array, it's an array-like object. More, in |
Marko Mikulicic |
0:c0ecb8bf28eb | 15445 | * non-strict mode, elements of `arguments` object are just aliases |
Marko Mikulicic |
0:c0ecb8bf28eb | 15446 | * for actual arguments, so this one: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15447 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15448 | * `(function(a){arguments[0]=2; return a;})(1);` |
Marko Mikulicic |
0:c0ecb8bf28eb | 15449 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15450 | * should yield 2. Currently, it yields 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15451 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15452 | v7_def(v7, scope_frame, "arguments", 9, V7_DESC_CONFIGURABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15453 | v2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15455 | /* populate local variables */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15456 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15457 | uint8_t loc_num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15458 | uint8_t loc_cnt = func->bcode->names_cnt - func->bcode->args_cnt - |
Marko Mikulicic |
0:c0ecb8bf28eb | 15459 | 1 /*func name*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15460 | for (loc_num = 0; loc_num < loc_cnt; ++loc_num) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15461 | ops = bcode_next_name_v(v7, func->bcode, ops, &v4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15462 | BTRY(def_property_v(v7, scope_frame, v4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15463 | V7_DESC_CONFIGURABLE(0), V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15464 | 0 /*not assign*/, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15465 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15466 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15467 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15468 | /* transfer control to the function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15469 | V7_TRY(bcode_perform_call(v7, scope_frame, func, &r, v3 /*this*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15470 | ops, is_constructor)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15472 | scope_frame = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15473 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15474 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15475 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15476 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15477 | case OP_RET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15478 | bcode_adjust_retval(v7, 1 /*explicit return*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15479 | V7_TRY(bcode_perform_return(v7, &r, 1 /*take value from stack*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15480 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15481 | case OP_DELETE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15482 | case OP_DELETE_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15483 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15484 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15486 | res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15488 | /* pop property name to delete */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15489 | v2 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15491 | if (op == OP_DELETE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15492 | /* pop object to delete the property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15493 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15494 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15495 | /* use scope as an object to delete the property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15496 | v1 = get_scope(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15499 | if (!v7_is_object(v1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15500 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15501 | * the "object" to delete a property from is not actually an object |
Marko Mikulicic |
0:c0ecb8bf28eb | 15502 | * (at least this can happen with cfunction pointers), will just |
Marko Mikulicic |
0:c0ecb8bf28eb | 15503 | * return `true` |
Marko Mikulicic |
0:c0ecb8bf28eb | 15504 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15505 | goto delete_clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15506 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15508 | BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), &name_len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15510 | prop = v7_get_property(v7, v1, buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15511 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15512 | /* not found a property; will just return `true` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15513 | goto delete_clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15514 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15515 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15516 | /* found needed property */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15518 | if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15519 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15520 | * this property is undeletable. In non-strict mode, we just |
Marko Mikulicic |
0:c0ecb8bf28eb | 15521 | * return `false`; otherwise, we throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15522 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15523 | if (!r.bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15524 | res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15525 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15526 | BTRY(v7_throwf(v7, TYPE_ERROR, "Cannot delete property '%s'", buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15527 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15528 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15529 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15530 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15531 | * delete property: when we operate on the current scope, we should |
Marko Mikulicic |
0:c0ecb8bf28eb | 15532 | * walk the prototype chain when deleting property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15533 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15534 | * But when we operate on a "real" object, we should delete own |
Marko Mikulicic |
0:c0ecb8bf28eb | 15535 | * properties only. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15536 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15537 | if (op == OP_DELETE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15538 | v7_del(v7, v1, buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15539 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15540 | del_property_deep(v7, v1, buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15541 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15544 | delete_clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15545 | PUSH(res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15546 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15547 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15548 | case OP_TRY_PUSH_CATCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15549 | case OP_TRY_PUSH_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15550 | case OP_TRY_PUSH_LOOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15551 | case OP_TRY_PUSH_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15552 | eval_try_push(v7, op, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15553 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15554 | case OP_TRY_POP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15555 | V7_TRY(eval_try_pop(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15556 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15557 | case OP_AFTER_FINALLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15558 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15559 | * exited from `finally` block: if some value is currently being |
Marko Mikulicic |
0:c0ecb8bf28eb | 15560 | * returned, continue returning it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15561 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15562 | * Likewise, if some value is currently being thrown, continue |
Marko Mikulicic |
0:c0ecb8bf28eb | 15563 | * unwinding stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15564 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15565 | if (v7->is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15566 | V7_TRY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15567 | bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15568 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15569 | } else if (v7->is_returned) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15570 | V7_TRY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 15571 | bcode_perform_return(v7, &r, 0 /*don't take value from stack*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15572 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15573 | } else if (v7->is_breaking) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15574 | bcode_perform_break(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15575 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15576 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15577 | case OP_THROW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15578 | V7_TRY(bcode_perform_throw(v7, &r, 1 /*take thrown value*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15579 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15580 | case OP_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15581 | bcode_perform_break(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15582 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15583 | case OP_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15584 | v7->is_continuing = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15585 | bcode_perform_break(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15586 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15587 | case OP_ENTER_CATCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15588 | /* pop thrown value from stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15589 | v1 = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15590 | /* get the name of the thrown value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15591 | v2 = bcode_decode_lit(v7, r.bcode, &r.ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15593 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15594 | * create a new stack frame (a "private" one), and set exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 15595 | * property on it |
Marko Mikulicic |
0:c0ecb8bf28eb | 15596 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15597 | scope_frame = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15598 | BTRY(set_property_v(v7, scope_frame, v2, v1, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15599 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15600 | /* Push this "private" frame on the call stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15601 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15602 | /* new scope_frame will inherit from the current scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15604 | obj_prototype_set(v7, get_object_struct(scope_frame), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15605 | get_object_struct(get_scope(v7))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15606 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15607 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15608 | * Create new `call_frame` which will replace `v7->call_stack`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15609 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15610 | append_call_frame_private(v7, scope_frame); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15612 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15613 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15614 | case OP_EXIT_CATCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15615 | v7_call_frame_mask_t frame_type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15616 | /* unwind 1 frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15617 | frame_type_mask = unwind_stack_1level(v7, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15618 | /* make sure the unwound frame is a "private" frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15619 | assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15620 | #if defined(NDEBUG) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15621 | (void) frame_type_mask; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15622 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15623 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15624 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15625 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15626 | BTRY(v7_throwf(v7, INTERNAL_ERROR, "Unknown opcode: %d", (int) op)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15627 | goto op_done; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15628 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15630 | op_done: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15631 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15632 | /* print current stack state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15633 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15634 | char buf[40]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15635 | char *str = v7_stringify(v7, TOS(), buf, sizeof(buf), V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15636 | fprintf(stderr, " stack size: %u, TOS: '%s'\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 15637 | (unsigned int) (v7->stack.len / sizeof(val_t)), str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15638 | if (str != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15639 | free(str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15640 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15641 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15642 | #ifdef V7_BCODE_TRACE_STACK |
Marko Mikulicic |
0:c0ecb8bf28eb | 15643 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15644 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15645 | for (i = 0; i < (v7->stack.len / sizeof(val_t)); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15646 | char *str = v7_stringify(v7, stack_at(&v7->stack, i), buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15647 | sizeof(buf), V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15649 | fprintf(stderr, " #: '%s'\n", str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15651 | if (str != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15652 | free(str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15653 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15654 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15655 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15656 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15657 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15658 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15659 | if (r.need_inc_ops) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15660 | r.ops++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15661 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15662 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15664 | /* implicit return */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15665 | if (v7->call_stack != v7->bottom_call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15666 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15667 | fprintf(stderr, "return implicitly\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15668 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15669 | bcode_adjust_retval(v7, 0 /*implicit return*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15670 | V7_TRY(bcode_perform_return(v7, &r, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15671 | goto restart; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15672 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15673 | #ifdef V7_BCODE_TRACE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15674 | const char *s = (get_scope(v7) != v7->vals.global_object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15675 | ? "not global object" |
Marko Mikulicic |
0:c0ecb8bf28eb | 15676 | : "global object"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15677 | fprintf(stderr, "reached bottom_call_frame (%s)\n", s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15678 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15679 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15680 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15681 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15683 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15684 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15685 | * bcode evaluated successfully. Make sure try stack is empty. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15686 | * (data stack will be checked below, in `clean`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15687 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15688 | #ifndef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 15689 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15690 | unsigned long try_stack_len = |
Marko Mikulicic |
0:c0ecb8bf28eb | 15691 | v7_array_length(v7, find_call_frame_private(v7)->vals.try_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15692 | if (try_stack_len != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15693 | fprintf(stderr, "try_stack_len=%lu, should be 0\n", try_stack_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15694 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15695 | assert(try_stack_len == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15696 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15697 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15699 | /* get the value returned from the evaluated script */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15700 | *_res = POP(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15701 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15702 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15703 | assert(v7->bottom_call_frame == v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15704 | unwind_stack_1level(v7, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15706 | v7->bottom_call_frame = saved_bottom_call_frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15708 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15709 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15710 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15711 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15712 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15713 | * TODO(dfrank) this function is probably too overloaded: it handles both |
Marko Mikulicic |
0:c0ecb8bf28eb | 15714 | * `v7_exec` and `v7_apply`. Read below why it's written this way, but it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 15715 | * probably a good idea to factor out common functionality in some other |
Marko Mikulicic |
0:c0ecb8bf28eb | 15716 | * function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15717 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15718 | * If `src` is not `NULL`, then we behave in favour of `v7_exec`: parse, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15719 | * compile, and evaluate the script. The `func` and `args` are ignored. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15720 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15721 | * If, however, `src` is `NULL`, then we behave in favour of `v7_apply`: we |
Marko Mikulicic |
0:c0ecb8bf28eb | 15722 | * call the provided `func` with `args`. But unlike interpreter, we can't just |
Marko Mikulicic |
0:c0ecb8bf28eb | 15723 | * call the provided function: we need to setup environment for this call. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15724 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15725 | * Currently, we just quickly generate the "wrapper" bcode for the function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15726 | * This wrapper bcode looks like this: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15727 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15728 | * OP_PUSH_UNDEFINED |
Marko Mikulicic |
0:c0ecb8bf28eb | 15729 | * OP_PUSH_LIT # push this |
Marko Mikulicic |
0:c0ecb8bf28eb | 15730 | * OP_PUSH_LIT # push function |
Marko Mikulicic |
0:c0ecb8bf28eb | 15731 | * OP_PUSH_LIT # push arg1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 15732 | * OP_PUSH_LIT # push arg2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 15733 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 15734 | * OP_PUSH_LIT # push argN |
Marko Mikulicic |
0:c0ecb8bf28eb | 15735 | * OP_CALL(N) # call function with N arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 15736 | * OP_SWAP_DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 15737 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15738 | * and then, bcode evaluator proceeds with this code. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15739 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15740 | * In fact, both cases (eval or apply) are quite similar: we should prepare |
Marko Mikulicic |
0:c0ecb8bf28eb | 15741 | * environment for the bcode evaluation in exactly the same way, and the only |
Marko Mikulicic |
0:c0ecb8bf28eb | 15742 | * different part is where we get the bcode from. This is why that |
Marko Mikulicic |
0:c0ecb8bf28eb | 15743 | * functionality is baked in the single function, but it would be good to make |
Marko Mikulicic |
0:c0ecb8bf28eb | 15744 | * it suck less. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15745 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15746 | V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15747 | const char *filename, val_t func, val_t args, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15748 | val_t this_object, int is_json, int fr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15749 | uint8_t is_constructor, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15750 | #if defined(V7_BCODE_TRACE_SRC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15751 | fprintf(stderr, "src:'%s'\n", src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15752 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15754 | /* TODO(mkm): use GC pool */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15755 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15756 | struct ast *a = (struct ast *) malloc(sizeof(struct ast)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15757 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15758 | size_t saved_stack_len = v7->stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15759 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15760 | val_t _res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15761 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15762 | struct bcode *bcode = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15763 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15764 | struct stack_track_ctx stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15765 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15766 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15767 | unsigned noopt : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15768 | unsigned line_no_reset : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15769 | } flags = {0, 0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15770 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15771 | (void) filename; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15773 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15774 | v7_stack_track_start(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15775 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15777 | tmp_stack_push(&tf, &func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15778 | tmp_stack_push(&tf, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15779 | tmp_stack_push(&tf, &this_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15780 | tmp_stack_push(&tf, &_res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15781 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15782 | /* init new bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15783 | bcode = (struct bcode *) calloc(1, sizeof(*bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15784 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15785 | bcode_init(bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15786 | #ifndef V7_FORCE_STRICT_MODE |
Marko Mikulicic |
0:c0ecb8bf28eb | 15787 | 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15788 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 15789 | 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15790 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15791 | #ifndef V7_DISABLE_FILENAMES |
Marko Mikulicic |
0:c0ecb8bf28eb | 15792 | filename ? shdata_create_from_string(filename) : NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15793 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 15794 | NULL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15795 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15796 | 0 /*filename not in ROM*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15797 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15799 | retain_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15800 | own_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15802 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15803 | ast_init(a, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15804 | a->refcnt = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15805 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15806 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15807 | if (src != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15808 | /* Caller provided some source code, so, handle it somehow */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15810 | flags.line_no_reset = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15812 | if (src_len >= sizeof(BIN_BCODE_SIGNATURE) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15813 | strncmp(BIN_BCODE_SIGNATURE, src, sizeof(BIN_BCODE_SIGNATURE)) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15814 | /* we have a serialized bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15816 | bcode_deserialize(v7, bcode, src + sizeof(BIN_BCODE_SIGNATURE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15817 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15818 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15819 | * Currently, we only support serialized bcode that is stored in some |
Marko Mikulicic |
0:c0ecb8bf28eb | 15820 | * mmapped memory. Otherwise, we don't yet have any mechanism to free |
Marko Mikulicic |
0:c0ecb8bf28eb | 15821 | * this memory at the appropriate time. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15822 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15824 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15825 | * TODO(dfrank): currently, we remove this assert, and introduce memory |
Marko Mikulicic |
0:c0ecb8bf28eb | 15826 | * leak. We need to support that properly. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15827 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15828 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 15829 | assert(fr == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15830 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 15831 | if (fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15832 | fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15833 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15834 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15835 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15836 | /* Maybe regular JavaScript source or binary AST data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15837 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15839 | if (src_len >= sizeof(BIN_AST_SIGNATURE) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 15840 | strncmp(BIN_AST_SIGNATURE, src, sizeof(BIN_AST_SIGNATURE)) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15841 | /* we have binary AST data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15843 | if (fr == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15844 | /* Unmanaged memory, usually rom or mmapped flash */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15845 | mbuf_free(&a->mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15846 | a->mbuf.buf = (char *) (src + sizeof(BIN_AST_SIGNATURE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15847 | a->mbuf.size = a->mbuf.len = src_len - sizeof(BIN_AST_SIGNATURE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15848 | a->refcnt++; /* prevent freeing */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15849 | flags.noopt = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15850 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15851 | mbuf_append(&a->mbuf, src + sizeof(BIN_AST_SIGNATURE), |
Marko Mikulicic |
0:c0ecb8bf28eb | 15852 | src_len - sizeof(BIN_AST_SIGNATURE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15853 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15854 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15855 | /* we have regular JavaScript source, so, parse it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15856 | V7_TRY(parse(v7, a, src, src_len, is_json)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15857 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15859 | /* we now have binary AST, let's compile it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15861 | if (!flags.noopt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15862 | ast_optimize(a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15864 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 15865 | v7->function_arena_ast_size += a->mbuf.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15866 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 15867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15868 | if (v7_is_undefined(this_object)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15869 | this_object = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15870 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15872 | if (!is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15873 | V7_TRY(compile_script(v7, a, bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15874 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15875 | ast_off_t pos = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15876 | V7_TRY(compile_expr(v7, a, &pos, bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15878 | #else /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15879 | (void) is_json; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15880 | /* Parsing JavaScript code is disabled */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15881 | rcode = v7_throwf(v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15882 | "Parsing JS code is disabled by V7_NO_COMPILER"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15883 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15884 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15885 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15887 | } else if (is_js_function(func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15888 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15889 | * Caller did not provide source code, so, assume we should call |
Marko Mikulicic |
0:c0ecb8bf28eb | 15890 | * provided function. Here, we prepare "wrapper" bcode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15891 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15893 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15894 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15895 | int args_cnt = v7_array_length(v7, args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15897 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15899 | bcode_op(&bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15901 | /* push `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15902 | lit = bcode_add_lit(&bbuilder, this_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15903 | bcode_push_lit(&bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15905 | /* push func literal */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15906 | lit = bcode_add_lit(&bbuilder, func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15907 | bcode_push_lit(&bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15909 | /* push args */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15910 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15911 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15912 | for (i = 0; i < args_cnt; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15913 | lit = bcode_add_lit(&bbuilder, v7_array_get(v7, args, i)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15914 | bcode_push_lit(&bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15916 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15918 | bcode_op(&bbuilder, OP_CALL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15919 | /* TODO(dfrank): check if args <= 0x7f */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15920 | bcode_op(&bbuilder, (uint8_t) args_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15922 | bcode_op(&bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15924 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15925 | } else if (is_cfunction_lite(func) || is_cfunction_obj(v7, func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15926 | /* call cfunction */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15928 | V7_TRY(call_cfunction(v7, func, this_object, args, is_constructor, &_res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15930 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15931 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15932 | /* value is not a function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15933 | V7_TRY(v7_throwf(v7, TYPE_ERROR, "value is not a function")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15934 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15936 | /* We now have bcode to evaluate; proceed to it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15937 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15938 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 15939 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15940 | * Before we evaluate bcode, we can safely release AST since it's not needed |
Marko Mikulicic |
0:c0ecb8bf28eb | 15941 | * anymore. Note that there's no leak here: if we `goto clean` from somewhere |
Marko Mikulicic |
0:c0ecb8bf28eb | 15942 | * above, we'll anyway release the AST under `clean` as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15943 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15944 | release_ast(v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15945 | a = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15946 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15948 | /* Evaluate bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15949 | V7_TRY(eval_bcode(v7, bcode, this_object, flags.line_no_reset, &_res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15950 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15951 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 15952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15953 | /* free `src` if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15954 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15955 | * TODO(dfrank) : free it above, just after parsing, and make sure you use |
Marko Mikulicic |
0:c0ecb8bf28eb | 15956 | * V7_TRY2() with custom label instead of V7_TRY() |
Marko Mikulicic |
0:c0ecb8bf28eb | 15957 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15958 | if (src != NULL && fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15959 | free((void *) src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15960 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15961 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15962 | /* disown and release current bcode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15963 | disown_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15964 | release_bcode(v7, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15965 | bcode = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15967 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15968 | /* some exception happened. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15969 | _res = v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15971 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15972 | * if this is a top-level bcode, clear thrown error from the v7 context |
Marko Mikulicic |
0:c0ecb8bf28eb | 15973 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15974 | * TODO(dfrank): do we really need to do this? |
Marko Mikulicic |
0:c0ecb8bf28eb | 15975 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15976 | * If we don't clear the error, then we should clear it manually after each |
Marko Mikulicic |
0:c0ecb8bf28eb | 15977 | * call to v7_exec() or friends; otherwise, all the following calls will |
Marko Mikulicic |
0:c0ecb8bf28eb | 15978 | * see this error. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15979 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 15980 | * On the other hand, user would still need to clear the error if he calls |
Marko Mikulicic |
0:c0ecb8bf28eb | 15981 | * v7_exec() from some cfunction. So, currently, sometimes we don't need |
Marko Mikulicic |
0:c0ecb8bf28eb | 15982 | * to clear the error, and sometimes we do, which is confusing. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15983 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15984 | if (v7->act_bcodes.len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15985 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15986 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 15987 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15988 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15989 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15990 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 15991 | * Data stack should have the same length as it was before evaluating script. |
Marko Mikulicic |
0:c0ecb8bf28eb | 15992 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 15993 | if (v7->stack.len != saved_stack_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 15994 | fprintf(stderr, "len=%d, saved=%d\n", (int) v7->stack.len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 15995 | (int) saved_stack_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15996 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 15997 | assert(v7->stack.len == saved_stack_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 15998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 15999 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16000 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16001 | * release AST if needed (normally, it's already released above, before |
Marko Mikulicic |
0:c0ecb8bf28eb | 16002 | * bcode evaluation) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16003 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16004 | if (a != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16005 | release_ast(v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16006 | a = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16008 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16010 | if (is_constructor && !v7_is_object(_res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16011 | /* constructor returned non-object: replace it with `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16012 | _res = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16013 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16015 | /* Provide the caller with the result, if asked to do so */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16016 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16017 | *res = _res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16019 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16020 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16021 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16022 | int diff = v7_stack_track_end(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16023 | if (diff > v7->stack_stat[V7_STACK_STAT_EXEC]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16024 | v7->stack_stat[V7_STACK_STAT_EXEC] = diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16025 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16027 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16029 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16030 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16031 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16033 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 16034 | V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16035 | v7_val_t args, uint8_t is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16036 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16037 | return b_exec(v7, NULL, 0, NULL, func, args, this_obj, 0, 0, is_constructor, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16038 | res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16040 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16041 | #line 1 "v7/src/core.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16042 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16043 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16044 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16045 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16046 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16047 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16048 | /* Amalgamated: #include "v7/builtin/builtin.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16049 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16050 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16051 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16052 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16053 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16054 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16055 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16056 | /* Amalgamated: #include "v7/src/stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16057 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16058 | /* Amalgamated: #include "v7/src/heapusage.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16059 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16061 | #ifdef V7_THAW |
Marko Mikulicic |
0:c0ecb8bf28eb | 16062 | extern struct v7_vals *fr_vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16063 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16065 | #ifdef HAS_V7_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 16066 | double _v7_infinity; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16067 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16069 | #ifdef HAS_V7_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 16070 | double _v7_nan; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16071 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16072 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16073 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16074 | struct v7 *v7_head = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16075 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16076 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16077 | static void generic_object_destructor(struct v7 *v7, void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16078 | struct v7_generic_object *o = (struct v7_generic_object *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16079 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16080 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16081 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16082 | /* TODO(mkm): make regexp use user data API */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16083 | p = v7_get_own_property2(v7, v7_object_to_value(&o->base), "", 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16084 | _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16085 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16086 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 16087 | if (p != NULL && (p->value & V7_TAG_MASK) == V7_TAG_REGEXP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16088 | struct v7_regexp *rp = (struct v7_regexp *) get_ptr(p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16089 | v7_disown(v7, &rp->regexp_string); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16090 | slre_free(rp->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16091 | free(rp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16093 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16095 | if (o->base.attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16096 | if (p != NULL && |
Marko Mikulicic |
0:c0ecb8bf28eb | 16097 | ((abuf = (struct mbuf *) v7_get_ptr(v7, p->value)) != NULL)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16098 | mbuf_free(abuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16099 | free(abuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16101 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16103 | if (o->base.attributes & V7_OBJ_HAS_DESTRUCTOR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16104 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16105 | for (p = o->base.properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16106 | if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16107 | if (v7_is_foreign(p->name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16108 | v7_destructor_cb_t *cb = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16109 | (v7_destructor_cb_t *) v7_get_ptr(v7, p->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16110 | cb(v7, v7_get_ptr(v7, p->value)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16112 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16113 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16114 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16115 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16116 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16117 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16118 | o->base.entity_id_base = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16119 | o->base.entity_id_spec = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16120 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16121 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16123 | static void function_destructor(struct v7 *v7, void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16124 | struct v7_js_function *f = (struct v7_js_function *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16125 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16126 | if (f == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16128 | if (f->bcode != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16129 | release_bcode(v7, f->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16130 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16132 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16133 | f->base.entity_id_base = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16134 | f->base.entity_id_spec = V7_ENTITY_ID_PART_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16135 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16136 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16138 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16139 | static void property_destructor(struct v7 *v7, void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16140 | struct v7_property *p = (struct v7_property *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16141 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16142 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16144 | p->entity_id = V7_ENTITY_ID_NONE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16145 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16146 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16147 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16148 | struct v7 *v7_create(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16149 | struct v7_create_opts opts; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16150 | memset(&opts, 0, sizeof(opts)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16151 | return v7_create_opt(opts); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16152 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16154 | struct v7 *v7_create_opt(struct v7_create_opts opts) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16155 | struct v7 *v7 = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16156 | char z = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16158 | #if defined(HAS_V7_INFINITY) || defined(HAS_V7_NAN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16159 | double zero = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16160 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16162 | #ifdef HAS_V7_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 16163 | _v7_infinity = 1.0 / zero; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16164 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16165 | #ifdef HAS_V7_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 16166 | _v7_nan = zero / zero; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16167 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16169 | if (opts.object_arena_size == 0) opts.object_arena_size = 200; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16170 | if (opts.function_arena_size == 0) opts.function_arena_size = 100; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16171 | if (opts.property_arena_size == 0) opts.property_arena_size = 400; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16173 | if ((v7 = (struct v7 *) calloc(1, sizeof(*v7))) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16174 | #ifdef V7_STACK_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16175 | v7->sp_limit = (void *) ((uintptr_t) opts.c_stack_base - (V7_STACK_SIZE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16176 | v7->sp_lwm = opts.c_stack_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16177 | #ifdef V7_STACK_GUARD_MIN_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16178 | v7_sp_limit = v7->sp_limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16179 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16180 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16182 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16183 | v7->next_v7 = v7_head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16184 | v7_head = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16185 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16187 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16188 | v7->gc_next_asn = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16189 | v7->gc_min_asn = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16190 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16192 | v7->cur_dense_prop = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16193 | (struct v7_property *) calloc(1, sizeof(struct v7_property)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16194 | gc_arena_init(&v7->generic_object_arena, sizeof(struct v7_generic_object), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16195 | opts.object_arena_size, 10, "object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16196 | v7->generic_object_arena.destructor = generic_object_destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16197 | gc_arena_init(&v7->function_arena, sizeof(struct v7_js_function), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16198 | opts.function_arena_size, 10, "function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16199 | v7->function_arena.destructor = function_destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16200 | gc_arena_init(&v7->property_arena, sizeof(struct v7_property), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16201 | opts.property_arena_size, 10, "property"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16202 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16203 | v7->property_arena.destructor = property_destructor; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16204 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16205 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16206 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16207 | * The compacting GC exploits the null terminator of the previous |
Marko Mikulicic |
0:c0ecb8bf28eb | 16208 | * string as marker. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16209 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16210 | mbuf_append(&v7->owned_strings, &z, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16212 | v7->inhibit_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16213 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16214 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16215 | v7->call_stack = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16216 | v7->bottom_call_frame = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16218 | #if defined(V7_THAW) && !defined(V7_FREEZE_NOT_READONLY) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16219 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16220 | struct v7_generic_object *obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16221 | v7->vals = *fr_vals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16222 | v7->vals.global_object = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16223 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16224 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16225 | * The global object has to be mutable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16226 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16227 | obj = get_generic_object_struct(v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16228 | *obj = *get_generic_object_struct(fr_vals->global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16229 | obj->base.attributes &= ~(V7_OBJ_NOT_EXTENSIBLE | V7_OBJ_OFF_HEAP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16230 | v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16232 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 16233 | init_stdlib(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16234 | init_file(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16235 | init_crypto(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16236 | init_socket(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16237 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16238 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16239 | v7->inhibit_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16240 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16242 | return v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16243 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16244 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16245 | val_t v7_get_global(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16246 | return v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16247 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16249 | void v7_destroy(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16250 | if (v7 == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16251 | gc_arena_destroy(v7, &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16252 | gc_arena_destroy(v7, &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16253 | gc_arena_destroy(v7, &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16255 | mbuf_free(&v7->owned_strings); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16256 | mbuf_free(&v7->owned_values); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16257 | mbuf_free(&v7->foreign_strings); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16258 | mbuf_free(&v7->json_visited_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16259 | mbuf_free(&v7->tmp_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16260 | mbuf_free(&v7->act_bcodes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16261 | mbuf_free(&v7->stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16263 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16264 | /* delete this v7 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16265 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16266 | struct v7 *v, **prevp = &v7_head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16267 | for (v = v7_head; v != NULL; prevp = &v->next_v7, v = v->next_v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16268 | if (v == v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16269 | *prevp = v->next_v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16270 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16271 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16272 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16273 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16274 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16275 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16276 | free(v7->cur_dense_prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16277 | free(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16278 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16280 | v7_val_t v7_get_this(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16281 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16282 | * By default, when there's no active call frame, will return Global Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 16283 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16284 | v7_val_t ret = v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16285 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16286 | struct v7_call_frame_base *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16287 | find_call_frame(v7, V7_CALL_FRAME_MASK_BCODE | V7_CALL_FRAME_MASK_CFUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16289 | if (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16290 | if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16291 | ret = ((struct v7_call_frame_bcode *) call_frame)->vals.this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16292 | } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16293 | ret = ((struct v7_call_frame_cfunc *) call_frame)->vals.this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16294 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16295 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16296 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16297 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16299 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16302 | V7_PRIVATE v7_val_t get_scope(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16303 | struct v7_call_frame_private *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16304 | (struct v7_call_frame_private *) find_call_frame( |
Marko Mikulicic |
0:c0ecb8bf28eb | 16305 | v7, V7_CALL_FRAME_MASK_PRIVATE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16307 | if (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16308 | return call_frame->vals.scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16309 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16310 | /* No active call frame, return global object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16311 | return v7->vals.global_object; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16313 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16314 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16315 | V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16316 | struct v7_call_frame_bcode *call_frame = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16317 | (struct v7_call_frame_bcode *) find_call_frame(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16318 | V7_CALL_FRAME_MASK_BCODE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16320 | if (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16321 | return call_frame->bcode->strict_mode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16322 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16323 | /* No active call frame, assume no strict mode */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16324 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16325 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16326 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16328 | v7_val_t v7_get_arguments(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16329 | return v7->vals.arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16330 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16332 | v7_val_t v7_arg(struct v7 *v7, unsigned long n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16333 | return v7_array_get(v7, v7->vals.arguments, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16336 | unsigned long v7_argc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16337 | return v7_array_length(v7, v7->vals.arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16338 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16340 | void v7_own(struct v7 *v7, v7_val_t *v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16341 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16342 | mbuf_append(&v7->owned_values, &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16343 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16345 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16346 | int v7_disown(struct v7 *v7, v7_val_t *v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16347 | v7_val_t **vp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 16348 | (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16350 | for (; (char *) vp >= v7->owned_values.buf; vp--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16351 | if (*vp == v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16352 | *vp = *(v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - |
Marko Mikulicic |
0:c0ecb8bf28eb | 16353 | sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16354 | v7->owned_values.len -= sizeof(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16355 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16356 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16357 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16358 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16359 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16362 | void v7_set_gc_enabled(struct v7 *v7, int enabled) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16363 | v7->inhibit_gc = !enabled; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16366 | void v7_interrupt(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16367 | v7->interrupted = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16368 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16370 | const char *v7_get_parser_error(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16371 | return v7->error_msg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16372 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16373 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16374 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16376 | int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16377 | assert(what < V7_STACK_STATS_CNT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16378 | return v7->stack_stat[what]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16381 | void v7_stack_stat_clean(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16382 | memset(v7->stack_stat, 0x00, sizeof(v7->stack_stat)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16383 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16385 | #endif /* V7_ENABLE_STACK_TRACKING */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16386 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16387 | #line 1 "v7/src/primitive.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16388 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16389 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16390 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16391 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16392 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16394 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16395 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16396 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16398 | /* Number {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16400 | NOINSTR static v7_val_t mk_number(double v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16401 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16402 | /* not every NaN is a JS NaN */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16403 | if (isnan(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16404 | res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16405 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16406 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16407 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16408 | val_t r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16409 | } u; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16410 | u.d = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16411 | res = u.r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16412 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16413 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16414 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16415 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16416 | NOINSTR static double get_double(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16417 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16418 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16419 | val_t v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16420 | } u; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16421 | u.v = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16422 | /* Due to NaN packing, any non-numeric value is already a valid NaN value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16423 | return u.d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16424 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16426 | NOINSTR static v7_val_t mk_boolean(int v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16427 | return (!!v) | V7_TAG_BOOLEAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16428 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16430 | NOINSTR static int get_bool(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16431 | if (v7_is_boolean(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16432 | return v & 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16433 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16434 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16435 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16436 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16438 | NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16439 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16440 | return mk_number(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16443 | NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16444 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16445 | return get_double(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16448 | NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16449 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16450 | return (int) get_double(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16451 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16453 | int v7_is_number(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16454 | return v == V7_TAG_NAN || !isnan(get_double(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16455 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16457 | V7_PRIVATE int is_finite(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16458 | return v7_is_number(v) && v != V7_TAG_NAN && !isinf(v7_get_double(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16459 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16461 | /* }}} Number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16463 | /* Boolean {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16465 | NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16466 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16467 | return mk_boolean(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16468 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16470 | NOINSTR int v7_get_bool(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16471 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16472 | return get_bool(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16473 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16475 | int v7_is_boolean(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16476 | return (v & V7_TAG_MASK) == V7_TAG_BOOLEAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16477 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16478 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16479 | /* }}} Boolean */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16481 | /* null {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16483 | NOINSTR v7_val_t v7_mk_null(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16484 | return V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16485 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16486 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16487 | int v7_is_null(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16488 | return v == V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16489 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16491 | /* }}} null */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16493 | /* undefined {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16494 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16495 | NOINSTR v7_val_t v7_mk_undefined(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16496 | return V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16499 | int v7_is_undefined(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16500 | return v == V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16501 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16502 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16503 | /* }}} undefined */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16504 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16505 | /* Foreign {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16507 | V7_PRIVATE val_t pointer_to_value(void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16508 | uint64_t n = ((uint64_t)(uintptr_t) p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16510 | assert((n & V7_TAG_MASK) == 0 || (n & V7_TAG_MASK) == (~0 & V7_TAG_MASK)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16511 | return n & ~V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16512 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16513 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16514 | V7_PRIVATE void *get_ptr(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16515 | return (void *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16516 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16518 | NOINSTR void *v7_get_ptr(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16519 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16520 | if (!v7_is_foreign(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16521 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16522 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16523 | return get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16525 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16526 | NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16527 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16528 | return pointer_to_value(p) | V7_TAG_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16529 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16531 | int v7_is_foreign(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16532 | return (v & V7_TAG_MASK) == V7_TAG_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16533 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16535 | /* }}} Foreign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16536 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16537 | #line 1 "v7/src/function.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16538 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16539 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16540 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16541 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16542 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16544 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16545 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16546 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16547 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16548 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16549 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16550 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16551 | static val_t js_function_to_value(struct v7_js_function *o) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16552 | return pointer_to_value(o) | V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16553 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16555 | V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16556 | struct v7_js_function *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16557 | assert(is_js_function(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16558 | ret = (struct v7_js_function *) get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16559 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16560 | if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_JS_FUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16561 | fprintf(stderr, "entity_id: not a function!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16562 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16563 | } else if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16564 | fprintf(stderr, "entity_id: not an object!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16565 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16566 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16567 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16568 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16569 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16571 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16572 | val_t mk_js_function(struct v7 *v7, struct v7_generic_object *scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16573 | val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16574 | struct v7_js_function *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16575 | val_t fval = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16576 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16577 | tmp_stack_push(&tf, &proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16578 | tmp_stack_push(&tf, &fval); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16580 | f = new_function(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16582 | if (f == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16583 | /* fval is left `null` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16584 | goto cleanup; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16585 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16586 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16587 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16588 | f->base.entity_id_base = V7_ENTITY_ID_PART_OBJ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16589 | f->base.entity_id_spec = V7_ENTITY_ID_PART_JS_FUNC; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16590 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16592 | fval = js_function_to_value(f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16594 | f->base.properties = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16595 | f->scope = scope; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16597 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16598 | * Before setting a `V7_OBJ_FUNCTION` flag, make sure we don't have |
Marko Mikulicic |
0:c0ecb8bf28eb | 16599 | * `V7_OBJ_DENSE_ARRAY` flag set |
Marko Mikulicic |
0:c0ecb8bf28eb | 16600 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16601 | assert(!(f->base.attributes & V7_OBJ_DENSE_ARRAY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16602 | f->base.attributes |= V7_OBJ_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16603 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16604 | /* TODO(mkm): lazily create these properties on first access */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16605 | if (v7_is_object(proto)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16606 | v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), fval); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16607 | v7_def(v7, fval, "prototype", 9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16608 | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0), proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16609 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16610 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16611 | cleanup: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16612 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16613 | return fval; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16614 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16616 | V7_PRIVATE int is_js_function(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16617 | return (v & V7_TAG_MASK) == V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16618 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16620 | V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 16621 | v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *f, int num_args) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16622 | val_t obj = mk_object(v7, v7->vals.function_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16623 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16624 | tmp_stack_push(&tf, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16625 | v7_def(v7, obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_cfunction(f)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16626 | if (num_args >= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16627 | v7_def(v7, obj, "length", 6, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16628 | V7_DESC_CONFIGURABLE(0)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16629 | v7_mk_number(v7, num_args)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16631 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16632 | return obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16633 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16634 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16635 | V7_PRIVATE v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16636 | v7_cfunction_t *f, int num_args, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16637 | v7_val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16638 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16639 | v7_val_t res = mk_cfunction_obj(v7, f, num_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16640 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16641 | tmp_stack_push(&tf, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16643 | v7_def(v7, res, "prototype", 9, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16644 | V7_DESC_CONFIGURABLE(0)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16645 | proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16646 | v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16647 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16648 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16649 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16651 | V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16652 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16653 | void *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16654 | v7_cfunction_t *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16655 | } u; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16656 | u.f = f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16657 | return pointer_to_value(u.p) | V7_TAG_CFUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16658 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16659 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16660 | V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16661 | v7_cfunction_t *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16663 | if (is_cfunction_lite(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16664 | /* Implementation is identical to get_ptr but is separate since |
Marko Mikulicic |
0:c0ecb8bf28eb | 16665 | * object pointers are not directly convertible to function pointers |
Marko Mikulicic |
0:c0ecb8bf28eb | 16666 | * according to ISO C and generates a warning in -Wpedantic mode. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16667 | ret = (v7_cfunction_t *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16668 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16669 | /* maybe cfunction object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16670 | |
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 | /* yes, it's cfunction object. Extract cfunction pointer from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16676 | ret = get_cfunction_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16678 | } |
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_PRIVATE int is_cfunction_lite(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16684 | return (v & V7_TAG_MASK) == V7_TAG_CFUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16685 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16687 | V7_PRIVATE int is_cfunction_obj(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16688 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16689 | if (v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16690 | /* extract the hidden property from a cfunction_object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16691 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16692 | p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16693 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16694 | v = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16695 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16697 | ret = is_cfunction_lite(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16698 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16699 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16700 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16702 | v7_val_t v7_mk_function(struct v7 *v7, v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16703 | return mk_cfunction_obj(v7, f, -1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16704 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16705 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16706 | v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16707 | v7_val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16708 | return mk_cfunction_obj_with_proto(v7, f, ~0, proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16709 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16711 | v7_val_t v7_mk_cfunction(v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16712 | return mk_cfunction_lite(f); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16713 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16714 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16715 | int v7_is_callable(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16716 | return is_js_function(v) || is_cfunction_lite(v) || is_cfunction_obj(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16717 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16718 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16719 | #line 1 "v7/src/exec.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16720 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16721 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16722 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16723 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16724 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16725 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16726 | /* osdep.h must be included before `cs_file.h` TODO(dfrank) : fix this */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16727 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16728 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16729 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16730 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16731 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16732 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16733 | /* Amalgamated: #include "v7/src/compiler.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16734 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16736 | enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16737 | return b_exec(v7, js_code, strlen(js_code), NULL, V7_UNDEFINED, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16738 | V7_UNDEFINED, 0, 0, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16739 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16741 | enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16742 | const struct v7_exec_opts *opts, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16743 | return b_exec(v7, js_code, strlen(js_code), opts->filename, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16744 | V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16745 | (opts->this_obj == 0 ? V7_UNDEFINED : opts->this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16746 | opts->is_json, 0, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16747 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16749 | enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16750 | return b_exec(v7, str, strlen(str), NULL, V7_UNDEFINED, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16751 | V7_UNDEFINED, 1, 0, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16752 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16754 | #ifndef V7_NO_FS |
Marko Mikulicic |
0:c0ecb8bf28eb | 16755 | static enum v7_err exec_file(struct v7 *v7, const char *path, val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16756 | int is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16757 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16758 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16759 | size_t file_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16760 | char *(*rd)(const char *, size_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16761 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16762 | rd = cs_read_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16763 | #ifdef V7_MMAP_EXEC |
Marko Mikulicic |
0:c0ecb8bf28eb | 16764 | rd = cs_mmap_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16765 | #ifdef V7_MMAP_EXEC_ONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 16766 | #define I_STRINGIFY(x) #x |
Marko Mikulicic |
0:c0ecb8bf28eb | 16767 | #define I_STRINGIFY2(x) I_STRINGIFY(x) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16768 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16769 | /* use mmap only for .js files */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16770 | if (strlen(path) <= 3 || strcmp(path + strlen(path) - 3, ".js") != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16771 | rd = cs_read_file; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16772 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16773 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16774 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16775 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16776 | if ((p = rd(path, &file_size)) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16777 | rcode = v7_throwf(v7, SYNTAX_ERROR, "cannot open [%s]", path); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16778 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16779 | * In order to maintain compat with existing API, we should save the |
Marko Mikulicic |
0:c0ecb8bf28eb | 16780 | * current exception value into `*res` |
Marko Mikulicic |
0:c0ecb8bf28eb | 16781 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 16782 | * TODO(dfrank): probably change API: clients can use |
Marko Mikulicic |
0:c0ecb8bf28eb | 16783 | *`v7_get_thrown_value()` now. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16784 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16785 | if (res != NULL) *res = v7_get_thrown_value(v7, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16786 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16787 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16788 | #ifndef V7_MMAP_EXEC |
Marko Mikulicic |
0:c0ecb8bf28eb | 16789 | int fr = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16790 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 16791 | int fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16792 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16793 | rcode = b_exec(v7, p, file_size, path, V7_UNDEFINED, V7_UNDEFINED, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16794 | V7_UNDEFINED, is_json, fr, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16795 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16796 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16797 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16798 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16799 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16800 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16801 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16804 | enum v7_err v7_exec_file(struct v7 *v7, const char *path, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16805 | return exec_file(v7, path, res, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16806 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16808 | enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16809 | return exec_file(v7, path, res, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16810 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16811 | #endif /* V7_NO_FS */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16813 | enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16814 | v7_val_t args, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16815 | return b_apply(v7, func, this_obj, args, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16816 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16817 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16818 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 16819 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 16820 | enum v7_err _v7_compile(const char *src, size_t js_code_size, int binary, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16821 | int use_bcode, FILE *fp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16822 | struct ast ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16823 | struct v7 *v7 = v7_create(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16824 | ast_off_t pos = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16825 | enum v7_err err; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16827 | v7->is_precompiling = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16829 | ast_init(&ast, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16830 | err = parse(v7, &ast, src, js_code_size, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16831 | if (err == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16832 | if (use_bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16833 | struct bcode bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16834 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16835 | * We don't set filename here, because the bcode will be just serialized |
Marko Mikulicic |
0:c0ecb8bf28eb | 16836 | * and then freed. We don't currently serialize filename. If we ever do, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16837 | * we'll have to make `_v7_compile()` to also take a filename argument, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16838 | * and use it here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 16839 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16840 | bcode_init(&bcode, 0, NULL, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16841 | err = compile_script(v7, &ast, &bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16842 | if (err != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16843 | goto cleanup_bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16846 | if (binary) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16847 | bcode_serialize(v7, &bcode, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16848 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16849 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 16850 | dump_bcode(v7, fp, &bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16851 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 16852 | fprintf(stderr, "build flag V7_BCODE_DUMP not enabled\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16853 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16854 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16855 | cleanup_bcode: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16856 | bcode_free(v7, &bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16857 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16858 | if (binary) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16859 | fwrite(BIN_AST_SIGNATURE, sizeof(BIN_AST_SIGNATURE), 1, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16860 | fwrite(ast.mbuf.buf, ast.mbuf.len, 1, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16861 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16862 | ast_dump_tree(fp, &ast, &pos, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16864 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16867 | ast_free(&ast); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16868 | v7_destroy(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16869 | return err; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16870 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16872 | enum v7_err v7_compile(const char *src, int binary, int use_bcode, FILE *fp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16873 | return _v7_compile(src, strlen(src), binary, use_bcode, fp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16874 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16875 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16876 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16877 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 16878 | #line 1 "v7/src/util.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 16879 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 16880 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 16881 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 16882 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 16883 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16885 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16886 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16887 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16888 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16889 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16890 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16891 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16892 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16893 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16894 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16895 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16897 | void v7_print(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16898 | v7_fprint(stdout, v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16899 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16901 | void v7_fprint(FILE *f, struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16902 | char buf[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16903 | char *s = v7_stringify(v7, v, buf, sizeof(buf), V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16904 | fprintf(f, "%s", s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16905 | if (buf != s) free(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16906 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16907 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16908 | void v7_println(struct v7 *v7, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16909 | v7_fprintln(stdout, v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16912 | void v7_fprintln(FILE *f, struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16913 | v7_fprint(f, v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16914 | fprintf(f, ENDL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16917 | void v7_fprint_stack_trace(FILE *f, struct v7 *v7, val_t e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16918 | size_t s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16919 | val_t strace_v = v7_get(v7, e, "stack", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16920 | const char *strace = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16921 | if (v7_is_string(strace_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16922 | strace = v7_get_string(v7, &strace_v, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16923 | fprintf(f, "%s\n", strace); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16924 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16925 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16927 | void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, val_t e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16928 | /* TODO(mkm): figure out if this is an error object and which kind */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16929 | v7_val_t msg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16930 | if (v7_is_undefined(e)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16931 | fprintf(f, "undefined error [%s]\n ", ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16932 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16933 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16934 | msg = v7_get(v7, e, "message", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16935 | if (v7_is_undefined(msg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16936 | msg = e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16937 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16938 | fprintf(f, "Exec error [%s]: ", ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16939 | v7_fprintln(f, v7, msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16940 | v7_fprint_stack_trace(f, v7, e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16943 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 16944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16945 | v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target, |
Marko Mikulicic |
0:c0ecb8bf28eb | 16946 | const v7_proxy_hnd_t *handler) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16947 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16948 | v7_val_t res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16949 | v7_val_t args = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16950 | v7_val_t handler_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16952 | v7_own(v7, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16953 | v7_own(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16954 | v7_own(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16955 | v7_own(v7, &target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16956 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16957 | /* if target is not an object, create one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16958 | if (!v7_is_object(target)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16959 | target = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16960 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16961 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16962 | /* prepare handler object with necessary properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16963 | handler_v = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16964 | if (handler->get != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16965 | set_cfunc_prop(v7, handler_v, "get", handler->get); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16966 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16967 | if (handler->set != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16968 | set_cfunc_prop(v7, handler_v, "set", handler->set); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16970 | if (handler->own_keys != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16971 | set_cfunc_prop(v7, handler_v, "ownKeys", handler->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16973 | if (handler->get_own_prop_desc != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16974 | v7_def(v7, handler_v, "_gpdc", ~0, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16975 | v7_mk_foreign(v7, (void *) handler->get_own_prop_desc)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16976 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16978 | /* prepare args */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16979 | args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16980 | v7_array_set(v7, args, 0, target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16981 | v7_array_set(v7, args, 1, handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16983 | /* call Proxy constructor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 16984 | V7_TRY(b_apply(v7, v7_get(v7, v7->vals.global_object, "Proxy", ~0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 16985 | v7_mk_object(v7), args, 1 /* as ctor */, &res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16987 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 16988 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 16989 | fprintf(stderr, "error during v7_mk_proxy()"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16990 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16991 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 16993 | v7_disown(v7, &target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16994 | v7_disown(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16995 | v7_disown(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16996 | v7_disown(v7, &res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 16997 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 16998 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 16999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17000 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17002 | V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17003 | int tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17004 | if (v7_is_number(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17005 | return V7_TYPE_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17007 | tag = (v & V7_TAG_MASK) >> 48; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17008 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17009 | case V7_TAG_FOREIGN >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17010 | if (v7_is_null(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17011 | return V7_TYPE_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17012 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17013 | return V7_TYPE_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17014 | case V7_TAG_UNDEFINED >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17015 | return V7_TYPE_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17016 | case V7_TAG_OBJECT >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17017 | if (v7_get_proto(v7, v) == v7->vals.array_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17018 | return V7_TYPE_ARRAY_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17019 | } else if (v7_get_proto(v7, v) == v7->vals.boolean_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17020 | return V7_TYPE_BOOLEAN_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17021 | } else if (v7_get_proto(v7, v) == v7->vals.string_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17022 | return V7_TYPE_STRING_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17023 | } else if (v7_get_proto(v7, v) == v7->vals.number_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17024 | return V7_TYPE_NUMBER_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17025 | } else if (v7_get_proto(v7, v) == v7->vals.function_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17026 | return V7_TYPE_CFUNCTION_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17027 | } else if (v7_get_proto(v7, v) == v7->vals.date_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17028 | return V7_TYPE_DATE_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17029 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17030 | return V7_TYPE_GENERIC_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17031 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17032 | case V7_TAG_STRING_I >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17033 | case V7_TAG_STRING_O >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17034 | case V7_TAG_STRING_F >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17035 | case V7_TAG_STRING_D >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17036 | case V7_TAG_STRING_5 >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17037 | return V7_TYPE_STRING; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17038 | case V7_TAG_BOOLEAN >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17039 | return V7_TYPE_BOOLEAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17040 | case V7_TAG_FUNCTION >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17041 | return V7_TYPE_FUNCTION_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17042 | case V7_TAG_CFUNCTION >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17043 | return V7_TYPE_CFUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17044 | case V7_TAG_REGEXP >> 48: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17045 | return V7_TYPE_REGEXP_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17046 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17047 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17048 | return V7_TYPE_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17049 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17050 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17052 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17053 | V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17054 | if ((b & 0x01) != (b >> 7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17055 | b ^= 0x81; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17056 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17057 | return b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17059 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17060 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 17061 | #line 1 "v7/src/string.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 17062 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17063 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17064 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 17065 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 17066 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17067 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17068 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17069 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17070 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17071 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17072 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17073 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17074 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17075 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17076 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17077 | /* Amalgamated: #include "v7/src/heapusage.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17079 | /* TODO(lsm): NaN payload location depends on endianness, make crossplatform */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17080 | #define GET_VAL_NAN_PAYLOAD(v) ((char *) &(v)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17081 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17082 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17083 | * Dictionary of read-only strings with length > 5. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17084 | * NOTE(lsm): must be sorted lexicographically, because |
Marko Mikulicic |
0:c0ecb8bf28eb | 17085 | * v_find_string_in_dictionary performs binary search over this list. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17086 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17087 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17088 | static const struct v7_vec_const v_dictionary_strings[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17089 | V7_VEC(" is not a function"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17090 | V7_VEC("Boolean"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17091 | V7_VEC("Crypto"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17092 | V7_VEC("EvalError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17093 | V7_VEC("Function"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17094 | V7_VEC("Infinity"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17095 | V7_VEC("InternalError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17096 | V7_VEC("LOG10E"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17097 | V7_VEC("MAX_VALUE"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17098 | V7_VEC("MIN_VALUE"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17099 | V7_VEC("NEGATIVE_INFINITY"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17100 | V7_VEC("Number"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17101 | V7_VEC("Object"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17102 | V7_VEC("POSITIVE_INFINITY"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17103 | V7_VEC("RangeError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17104 | V7_VEC("ReferenceError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17105 | V7_VEC("RegExp"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17106 | V7_VEC("SQRT1_2"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17107 | V7_VEC("Socket"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17108 | V7_VEC("String"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17109 | V7_VEC("SyntaxError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17110 | V7_VEC("TypeError"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17111 | V7_VEC("UBJSON"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17112 | V7_VEC("_modcache"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17113 | V7_VEC("accept"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17114 | V7_VEC("arguments"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17115 | V7_VEC("base64_decode"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17116 | V7_VEC("base64_encode"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17117 | V7_VEC("boolean"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17118 | V7_VEC("charAt"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17119 | V7_VEC("charCodeAt"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17120 | V7_VEC("concat"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17121 | V7_VEC("configurable"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17122 | V7_VEC("connect"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17123 | V7_VEC("constructor"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17124 | V7_VEC("create"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17125 | V7_VEC("defineProperties"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17126 | V7_VEC("defineProperty"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17127 | V7_VEC("every"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17128 | V7_VEC("exists"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17129 | V7_VEC("exports"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17130 | V7_VEC("filter"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17131 | V7_VEC("forEach"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17132 | V7_VEC("fromCharCode"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17133 | V7_VEC("function"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17134 | V7_VEC("getDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17135 | V7_VEC("getDay"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17136 | V7_VEC("getFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17137 | V7_VEC("getHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17138 | V7_VEC("getMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17139 | V7_VEC("getMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17140 | V7_VEC("getMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17141 | V7_VEC("getOwnPropertyDescriptor"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17142 | V7_VEC("getOwnPropertyNames"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17143 | V7_VEC("getPrototypeOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17144 | V7_VEC("getSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17145 | V7_VEC("getTime"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17146 | V7_VEC("getTimezoneOffset"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17147 | V7_VEC("getUTCDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17148 | V7_VEC("getUTCDay"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17149 | V7_VEC("getUTCFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17150 | V7_VEC("getUTCHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17151 | V7_VEC("getUTCMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17152 | V7_VEC("getUTCMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17153 | V7_VEC("getUTCMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17154 | V7_VEC("getUTCSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17155 | V7_VEC("global"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17156 | V7_VEC("hasOwnProperty"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17157 | V7_VEC("ignoreCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17158 | V7_VEC("indexOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17159 | V7_VEC("isArray"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17160 | V7_VEC("isExtensible"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17161 | V7_VEC("isFinite"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17162 | V7_VEC("isPrototypeOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17163 | V7_VEC("lastIndex"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17164 | V7_VEC("lastIndexOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17165 | V7_VEC("length"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17166 | V7_VEC("listen"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17167 | V7_VEC("loadJSON"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17168 | V7_VEC("localeCompare"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17169 | V7_VEC("md5_hex"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17170 | V7_VEC("module"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17171 | V7_VEC("multiline"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17172 | V7_VEC("number"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17173 | V7_VEC("parseFloat"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17174 | V7_VEC("parseInt"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17175 | V7_VEC("preventExtensions"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17176 | V7_VEC("propertyIsEnumerable"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17177 | V7_VEC("prototype"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17178 | V7_VEC("random"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17179 | V7_VEC("recvAll"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17180 | V7_VEC("reduce"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17181 | V7_VEC("remove"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17182 | V7_VEC("rename"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17183 | V7_VEC("render"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17184 | V7_VEC("replace"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17185 | V7_VEC("require"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17186 | V7_VEC("reverse"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17187 | V7_VEC("search"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17188 | V7_VEC("setDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17189 | V7_VEC("setFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17190 | V7_VEC("setHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17191 | V7_VEC("setMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17192 | V7_VEC("setMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17193 | V7_VEC("setMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17194 | V7_VEC("setSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17195 | V7_VEC("setTime"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17196 | V7_VEC("setUTCDate"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17197 | V7_VEC("setUTCFullYear"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17198 | V7_VEC("setUTCHours"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17199 | V7_VEC("setUTCMilliseconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17200 | V7_VEC("setUTCMinutes"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17201 | V7_VEC("setUTCMonth"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17202 | V7_VEC("setUTCSeconds"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17203 | V7_VEC("sha1_hex"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17204 | V7_VEC("source"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17205 | V7_VEC("splice"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17206 | V7_VEC("string"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17207 | V7_VEC("stringify"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17208 | V7_VEC("substr"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17209 | V7_VEC("substring"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17210 | V7_VEC("toDateString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17211 | V7_VEC("toExponential"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17212 | V7_VEC("toFixed"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17213 | V7_VEC("toISOString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17214 | V7_VEC("toJSON"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17215 | V7_VEC("toLocaleDateString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17216 | V7_VEC("toLocaleLowerCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17217 | V7_VEC("toLocaleString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17218 | V7_VEC("toLocaleTimeString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17219 | V7_VEC("toLocaleUpperCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17220 | V7_VEC("toLowerCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17221 | V7_VEC("toPrecision"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17222 | V7_VEC("toString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17223 | V7_VEC("toTimeString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17224 | V7_VEC("toUTCString"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17225 | V7_VEC("toUpperCase"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17226 | V7_VEC("valueOf"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17227 | V7_VEC("writable"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 17228 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17229 | /* clang-format on */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17230 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17231 | int nextesc(const char **p); /* from SLRE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17232 | V7_PRIVATE size_t unescape(const char *s, size_t len, char *to) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17233 | const char *end = s + len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17234 | size_t n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17235 | char tmp[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17236 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17238 | while (s < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17239 | s += chartorune(&r, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17240 | if (r == '\\' && s < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17241 | switch (*s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17242 | case '"': |
Marko Mikulicic |
0:c0ecb8bf28eb | 17243 | s++, r = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17244 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17245 | case '\'': |
Marko Mikulicic |
0:c0ecb8bf28eb | 17246 | s++, r = '\''; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17247 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17248 | case '\n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 17249 | s++, r = '\n'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17250 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17251 | default: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17252 | const char *tmp_s = s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17253 | int i = nextesc(&s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17254 | switch (i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17255 | case -SLRE_INVALID_ESC_CHAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17256 | r = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17257 | s = tmp_s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17258 | n += runetochar(to == NULL ? tmp : to + n, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17259 | s += chartorune(&r, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17260 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17261 | case -SLRE_INVALID_HEX_DIGIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17262 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17263 | r = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17264 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17265 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17266 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17267 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17268 | n += runetochar(to == NULL ? tmp : to + n, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17271 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17272 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17274 | static int v_find_string_in_dictionary(const char *s, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17275 | size_t start = 0, end = ARRAY_SIZE(v_dictionary_strings); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17277 | while (s != NULL && start < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17278 | size_t mid = start + (end - start) / 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17279 | const struct v7_vec_const *v = &v_dictionary_strings[mid]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17280 | size_t min_len = len < v->len ? len : v->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17281 | int comparison_result = memcmp(s, v->p, min_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17282 | if (comparison_result == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17283 | comparison_result = len - v->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17284 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17285 | if (comparison_result < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17286 | end = mid; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17287 | } else if (comparison_result > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17288 | start = mid + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17289 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17290 | return mid; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17291 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17292 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17293 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17294 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17296 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 17297 | V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, val_t obj, val_t arg, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17298 | double *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17299 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17300 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17301 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17302 | const char *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17303 | double at = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17305 | *res = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17307 | rcode = to_string(v7, obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17308 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17309 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17310 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17312 | p = v7_get_string(v7, &s, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17314 | n = utfnlen(p, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17315 | if (v7_is_number(arg) && at >= 0 && at < n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17316 | Rune r = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17317 | p = utfnshift(p, at); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17318 | chartorune(&r, (char *) p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17319 | *res = r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17320 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17321 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17322 | *res = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17323 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17324 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17325 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17326 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17327 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17328 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17330 | V7_PRIVATE int s_cmp(struct v7 *v7, val_t a, val_t b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17331 | size_t a_len, b_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17332 | const char *a_ptr, *b_ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17334 | a_ptr = v7_get_string(v7, &a, &a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17335 | b_ptr = v7_get_string(v7, &b, &b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17337 | if (a_len == b_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17338 | return memcmp(a_ptr, b_ptr, a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17339 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17340 | if (a_len > b_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17341 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17342 | } else if (a_len < b_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17343 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17344 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17345 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17346 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17347 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17348 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17349 | V7_PRIVATE val_t s_concat(struct v7 *v7, val_t a, val_t b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17350 | size_t a_len, b_len, res_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17351 | const char *a_ptr, *b_ptr, *res_ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17352 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17354 | /* Find out lengths of both srtings */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17355 | a_ptr = v7_get_string(v7, &a, &a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17356 | b_ptr = v7_get_string(v7, &b, &b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17358 | /* Create an placeholder string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17359 | res = v7_mk_string(v7, NULL, a_len + b_len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17361 | /* v7_mk_string() may have reallocated mbuf - revalidate pointers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17362 | a_ptr = v7_get_string(v7, &a, &a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17363 | b_ptr = v7_get_string(v7, &b, &b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17365 | /* Copy strings into the placeholder */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17366 | res_ptr = v7_get_string(v7, &res, &res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17367 | memcpy((char *) res_ptr, a_ptr, a_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17368 | memcpy((char *) res_ptr + a_len, b_ptr, b_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17370 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17371 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17373 | V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17374 | char *e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17375 | unsigned long res = strtoul(s, &e, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17376 | *ok = (e == s + len) && len != 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17377 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17378 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17380 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 17381 | V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17382 | unsigned long *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17383 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17384 | char buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17385 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17387 | V7_TRY(to_string(v7, v, NULL, buf, sizeof(buf), &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17389 | *res = cstr_to_ulong(buf, len, ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17391 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17392 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17394 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17395 | /* Insert a string into mbuf at specified offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17396 | V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17397 | size_t len, uint8_t /*enum embstr_flags*/ flags) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17398 | char *old_base = m->buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17399 | uint8_t p_backed_by_mbuf = p >= old_base && p < old_base + m->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17400 | size_t n = (flags & EMBSTR_UNESCAPE) ? unescape(p, len, NULL) : len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17402 | /* Calculate how many bytes length takes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17403 | int k = calc_llen(n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17405 | /* total length: varing length + string len + zero-term */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17406 | size_t tot_len = k + n + !!(flags & EMBSTR_ZERO_TERM); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17408 | /* Allocate buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17409 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17410 | mbuf_insert(m, offset, NULL, tot_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17411 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17413 | /* Fixup p if it was relocated by mbuf_insert() above */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17414 | if (p_backed_by_mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17415 | p += m->buf - old_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17417 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17418 | /* Write length */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17419 | encode_varint(n, (unsigned char *) m->buf + offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17421 | /* Write string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17422 | if (p != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17423 | if (flags & EMBSTR_UNESCAPE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17424 | unescape(p, len, m->buf + offset + k); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17425 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17426 | memcpy(m->buf + offset + k, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17427 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17428 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17430 | /* add NULL-terminator if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17431 | if (flags & EMBSTR_ZERO_TERM) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17432 | m->buf[offset + tot_len - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17433 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17434 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17436 | /* Create a string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17437 | v7_val_t v7_mk_string(struct v7 *v7, const char *p, size_t len, int copy) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17438 | struct mbuf *m = copy ? &v7->owned_strings : &v7->foreign_strings; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17439 | val_t offset = m->len, tag = V7_TAG_STRING_F; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17440 | int dict_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17442 | #ifdef V7_GC_AFTER_STRING_ALLOC |
Marko Mikulicic |
0:c0ecb8bf28eb | 17443 | v7->need_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17444 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17446 | if (len == ~((size_t) 0)) len = strlen(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17448 | if (len <= 4) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17449 | char *s = GET_VAL_NAN_PAYLOAD(offset) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17450 | offset = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17451 | if (p != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17452 | memcpy(s, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17453 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17454 | s[-1] = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17455 | tag = V7_TAG_STRING_I; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17456 | } else if (len == 5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17457 | char *s = GET_VAL_NAN_PAYLOAD(offset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17458 | offset = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17459 | if (p != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17460 | memcpy(s, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17462 | tag = V7_TAG_STRING_5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17463 | } else if ((dict_index = v_find_string_in_dictionary(p, len)) >= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17464 | offset = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17465 | GET_VAL_NAN_PAYLOAD(offset)[0] = dict_index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17466 | tag = V7_TAG_STRING_D; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17467 | } else if (copy) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17468 | compute_need_gc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17470 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17471 | * Before embedding new string, check if the reallocation is needed. If |
Marko Mikulicic |
0:c0ecb8bf28eb | 17472 | * so, perform the reallocation by calling `mbuf_resize` manually, since we |
Marko Mikulicic |
0:c0ecb8bf28eb | 17473 | * need to preallocate some extra space (`_V7_STRING_BUF_RESERVE`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17474 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17475 | if ((m->len + len) > m->size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17476 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17477 | mbuf_resize(m, m->len + len + _V7_STRING_BUF_RESERVE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17478 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17479 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17480 | embed_string(m, m->len, p, len, EMBSTR_ZERO_TERM); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17481 | tag = V7_TAG_STRING_O; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17482 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17483 | /* TODO(imax): panic if offset >= 2^32. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17484 | offset |= ((val_t) gc_next_allocation_seqn(v7, p, len)) << 32; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17485 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17486 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17487 | /* foreign string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17488 | if (sizeof(void *) <= 4 && len <= UINT16_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17489 | /* small foreign strings can fit length and ptr in the val_t */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17490 | offset = (uint64_t) len << 32 | (uint64_t)(uintptr_t) p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17491 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17492 | /* bigger strings need indirection that uses ram */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17493 | size_t pos = m->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17494 | int llen = calc_llen(len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17495 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17496 | /* allocate space for len and ptr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17497 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17498 | mbuf_insert(m, pos, NULL, llen + sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17499 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17500 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17501 | encode_varint(len, (uint8_t *) (m->buf + pos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17502 | memcpy(m->buf + pos + llen, &p, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17503 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17504 | tag = V7_TAG_STRING_F; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17505 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17507 | /* NOTE(lsm): don't use pointer_to_value, 32-bit ptrs will truncate */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17508 | return (offset & ~V7_TAG_MASK) | tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17509 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17511 | int v7_is_string(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17512 | uint64_t t = v & V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17513 | return t == V7_TAG_STRING_I || t == V7_TAG_STRING_F || t == V7_TAG_STRING_O || |
Marko Mikulicic |
0:c0ecb8bf28eb | 17514 | t == V7_TAG_STRING_5 || t == V7_TAG_STRING_D; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17517 | /* Get a pointer to string and string length. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17518 | const char *v7_get_string(struct v7 *v7, val_t *v, size_t *sizep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17519 | uint64_t tag = v[0] & V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17520 | const char *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17521 | int llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17522 | size_t size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17523 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17524 | if (!v7_is_string(*v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17525 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17526 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17528 | if (tag == V7_TAG_STRING_I) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17529 | p = GET_VAL_NAN_PAYLOAD(*v) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17530 | size = p[-1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17531 | } else if (tag == V7_TAG_STRING_5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17532 | p = GET_VAL_NAN_PAYLOAD(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17533 | size = 5; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17534 | } else if (tag == V7_TAG_STRING_D) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17535 | int index = ((unsigned char *) GET_VAL_NAN_PAYLOAD(*v))[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17536 | size = v_dictionary_strings[index].len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17537 | p = v_dictionary_strings[index].p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17538 | } else if (tag == V7_TAG_STRING_O) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17539 | size_t offset = (size_t) gc_string_val_to_offset(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17540 | char *s = v7->owned_strings.buf + offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17542 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17543 | gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17544 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17546 | size = decode_varint((uint8_t *) s, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17547 | p = s + llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17548 | } else if (tag == V7_TAG_STRING_F) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17549 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17550 | * short foreign strings on <=32-bit machines can be encoded in a compact |
Marko Mikulicic |
0:c0ecb8bf28eb | 17551 | * form: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17552 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17553 | * 7 6 5 4 3 2 1 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 17554 | * 11111111|1111tttt|llllllll|llllllll|ssssssss|ssssssss|ssssssss|ssssssss |
Marko Mikulicic |
0:c0ecb8bf28eb | 17555 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17556 | * Strings longer than 2^26 will be indireceted through the foreign_strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 17557 | * mbuf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17558 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17559 | * We don't use a different tag to represent those two cases. Instead, all |
Marko Mikulicic |
0:c0ecb8bf28eb | 17560 | * foreign strings represented with the help of the foreign_strings mbuf |
Marko Mikulicic |
0:c0ecb8bf28eb | 17561 | * will have the upper 16-bits of the payload set to zero. This allows us to |
Marko Mikulicic |
0:c0ecb8bf28eb | 17562 | * represent up to 477 million foreign strings longer than 64k. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17563 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17564 | uint16_t len = (*v >> 32) & 0xFFFF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17565 | if (sizeof(void *) <= 4 && len != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17566 | size = (size_t) len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17567 | p = (const char *) (uintptr_t) *v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17568 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17569 | size_t offset = (size_t) gc_string_val_to_offset(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17570 | char *s = v7->foreign_strings.buf + offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17572 | size = decode_varint((uint8_t *) s, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17573 | memcpy(&p, s + llen, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17574 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17575 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17576 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17577 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17578 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17579 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17580 | if (sizep != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17581 | *sizep = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17582 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17583 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17584 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17586 | const char *v7_get_cstring(struct v7 *v7, v7_val_t *value) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17587 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17588 | const char *s = v7_get_string(v7, value, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17589 | if (s == NULL) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17590 | if (s[size] != 0 || strlen(s) != size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17591 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17592 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17593 | return s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17594 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17595 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 17596 | #line 1 "v7/src/array.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 17597 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17598 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17599 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 17600 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 17601 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17603 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17604 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17605 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17606 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17607 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17608 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17609 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17610 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17612 | /* like c_snprintf but returns `size` if write is truncated */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17613 | static int v_sprintf_s(char *buf, size_t size, const char *fmt, ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17614 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17615 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17616 | va_start(ap, fmt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17617 | n = c_vsnprintf(buf, size, fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17618 | if (n > size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17619 | return size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17620 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17621 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17624 | v7_val_t v7_mk_array(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17625 | val_t a = mk_object(v7, v7->vals.array_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17626 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 17627 | v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17628 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17629 | return a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17631 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17632 | int v7_is_array(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17633 | return v7_is_generic_object(v) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 17634 | is_prototype_of(v7, v, v7->vals.array_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17635 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17637 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17638 | * Dense arrays are backed by mbuf. Currently the array can only grow by |
Marko Mikulicic |
0:c0ecb8bf28eb | 17639 | * appending (i.e. setting an element whose index == array.length) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17640 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 17641 | * TODO(mkm): automatically promote dense arrays to normal objects |
Marko Mikulicic |
0:c0ecb8bf28eb | 17642 | * when they are used as sparse arrays or to store arbitrary keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 17643 | * (perhaps a hybrid approach) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17644 | * TODO(mkm): small sparsness doesn't have to promote the array, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17645 | * we can just fill empty slots with a tag. In JS missing array |
Marko Mikulicic |
0:c0ecb8bf28eb | 17646 | * indices are subtly different from indices with an undefined value |
Marko Mikulicic |
0:c0ecb8bf28eb | 17647 | * (key iteration). |
Marko Mikulicic |
0:c0ecb8bf28eb | 17648 | * TODO(mkm): change the interpreter so it can set elements in dense arrays |
Marko Mikulicic |
0:c0ecb8bf28eb | 17649 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17650 | V7_PRIVATE val_t v7_mk_dense_array(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17651 | val_t a = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17652 | #ifdef V7_ENABLE_DENSE_ARRAYS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17653 | v7_own(v7, &a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17654 | v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17656 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17657 | * Before setting a `V7_OBJ_DENSE_ARRAY` flag, make sure we don't have |
Marko Mikulicic |
0:c0ecb8bf28eb | 17658 | * `V7_OBJ_FUNCTION` flag set |
Marko Mikulicic |
0:c0ecb8bf28eb | 17659 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17660 | assert(!(get_object_struct(a)->attributes & V7_OBJ_FUNCTION)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17661 | get_object_struct(a)->attributes |= V7_OBJ_DENSE_ARRAY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17663 | v7_disown(v7, &a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17664 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17665 | return a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17666 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17668 | /* TODO_V7_ERR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17669 | val_t v7_array_get(struct v7 *v7, val_t arr, unsigned long index) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17670 | return v7_array_get2(v7, arr, index, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17671 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17673 | /* TODO_V7_ERR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17674 | val_t v7_array_get2(struct v7 *v7, val_t arr, unsigned long index, int *has) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17675 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17676 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17678 | if (has != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17679 | *has = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17680 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17681 | if (v7_is_object(arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17682 | if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17683 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17684 | v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17685 | struct mbuf *abuf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17686 | unsigned long len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17687 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17688 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17689 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17690 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17691 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17692 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17693 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17694 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17695 | if (index >= len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17696 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17697 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17698 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17699 | memcpy(&res, abuf->buf + index * sizeof(val_t), sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17700 | if (has != NULL && res != V7_TAG_NOVALUE) *has = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17701 | if (res == V7_TAG_NOVALUE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17702 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17703 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17704 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17705 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17706 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17707 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17708 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17709 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17710 | p = v7_get_property(v7, arr, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17711 | if (has != NULL && p != NULL) *has = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17712 | V7_TRY(v7_property_value(v7, arr, p, &res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17713 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17714 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17715 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17716 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17717 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17718 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17719 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17720 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17721 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17722 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17723 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17725 | #if V7_ENABLE_DENSE_ARRAYS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17727 | /* Create V7 strings for integers such as array indices */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17728 | static val_t ulong_to_str(struct v7 *v7, unsigned long n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17729 | char buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17730 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17731 | len = c_snprintf(buf, sizeof(buf), "%lu", n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17732 | return v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17733 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17735 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17736 | * Pack 15-bit length and 15 bit index, leaving 2 bits for tag. the LSB has to |
Marko Mikulicic |
0:c0ecb8bf28eb | 17737 | * be set to distinguish it from a prop pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 17738 | * In alternative we just fetch the length from obj at each call to v7_next_prop |
Marko Mikulicic |
0:c0ecb8bf28eb | 17739 | * and just stuff the index here (e.g. on 8/16-bit platforms). |
Marko Mikulicic |
0:c0ecb8bf28eb | 17740 | * TODO(mkm): conditional for 16-bit platforms |
Marko Mikulicic |
0:c0ecb8bf28eb | 17741 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17742 | #define PACK_ITER(len, idx) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17743 | ((struct v7_property *) ((len) << 17 | (idx) << 1 | 1)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17745 | #define UNPACK_ITER_LEN(p) (((uintptr_t) p) >> 17) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17746 | #define UNPACK_ITER_IDX(p) ((((uintptr_t) p) >> 1) & 0x7FFF) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17747 | #define IS_PACKED_ITER(p) ((uintptr_t) p & 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17749 | void *v7_next_prop(struct v7 *v7, val_t obj, void *h, val_t *name, val_t *val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17750 | v7_prop_attr_t *attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17751 | struct v7_property *p = (struct v7_property *) h; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17753 | if (get_object_struct(obj)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17754 | /* This is a dense array. Find backing mbuf and fetch values from there */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17755 | struct v7_property *hp = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17756 | v7_get_own_property2(v7, obj, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17757 | struct mbuf *abuf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17758 | unsigned long len, idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17759 | if (hp != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17760 | abuf = (struct mbuf *) v7_get_ptr(v7, hp->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17761 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17762 | if (abuf == NULL) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17763 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17764 | if (len == 0) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17765 | idx = (p == NULL) ? 0 : UNPACK_ITER_IDX(p) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17766 | p = (idx == len) ? get_object_struct(obj)->properties : PACK_ITER(len, idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17767 | if (val != NULL) *val = ((val_t *) abuf->buf)[idx]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17768 | if (attrs != NULL) *attrs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17769 | if (name != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17770 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17771 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17772 | *name = v7_mk_string(v7, buf, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17773 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17774 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17775 | /* Ordinary object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17776 | p = (p == NULL) ? get_object_struct(obj)->properties : p->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17777 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17778 | if (name != NULL) *name = p->name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17779 | if (val != NULL) *val = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17780 | if (attrs != NULL) *attrs = p->attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17781 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17782 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17784 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17786 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17787 | V7_PRIVATE val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 17788 | v7_iter_get_value(struct v7 *v7, val_t obj, struct v7_property *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17789 | return IS_PACKED_ITER(p) ? v7_array_get(v7, obj, UNPACK_ITER_IDX(p)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17790 | : p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17791 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17793 | V7_PRIVATE val_t v7_iter_get_name(struct v7 *v7, struct v7_property *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17794 | return IS_PACKED_ITER(p) ? ulong_to_str(v7, UNPACK_ITER_IDX(p)) : p->name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17797 | V7_PRIVATE uint8_t v7_iter_get_attrs(struct v7_property *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17798 | return IS_PACKED_ITER(p) ? 0 : p->attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17799 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17800 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17801 | /* return array index as number or undefined. works with iterators */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17802 | V7_PRIVATE enum v7_err v7_iter_get_index(struct v7 *v7, struct v7_property *p, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17803 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17804 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17805 | int ok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17806 | unsigned long res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17807 | if (IS_PACKED_ITER(p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17808 | *res = v7_mk_number(v7, UNPACK_ITER_IDX(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17809 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17810 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17811 | V7_TRY(str_to_ulong(v7, p->name, &ok, &res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17812 | if (!ok || res >= UINT32_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17813 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17815 | *res = v7_mk_number(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17816 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17817 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17818 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17819 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17820 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17821 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17823 | /* TODO_V7_ERR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17824 | unsigned long v7_array_length(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17825 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17826 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17827 | unsigned long len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17829 | if (!v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17830 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17831 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17832 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17834 | #if V7_ENABLE_DENSE_ARRAYS |
Marko Mikulicic |
0:c0ecb8bf28eb | 17835 | if (get_object_struct(v)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17836 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17837 | v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17838 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17839 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17840 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17841 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17842 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17843 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17844 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17845 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17846 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17848 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17849 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17850 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17851 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17853 | for (p = get_object_struct(v)->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17854 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17855 | unsigned long n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17856 | V7_TRY(str_to_ulong(v7, p->name, &ok, &n)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17857 | if (ok && n >= len && n < UINT32_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17858 | len = n + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17859 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17860 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17861 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17862 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17863 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17864 | return len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17867 | int v7_array_set(struct v7 *v7, val_t arr, unsigned long index, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17868 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17869 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17870 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17871 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17873 | rcode = v7_array_set_throwing(v7, arr, index, v, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17874 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17875 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17876 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17877 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17878 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17879 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17880 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17881 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17882 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17884 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17885 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17887 | enum v7_err v7_array_set_throwing(struct v7 *v7, val_t arr, unsigned long index, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17888 | val_t v, int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17889 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17890 | int ires = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17892 | if (v7_is_object(arr)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17893 | if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17894 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 17895 | v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17896 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17897 | unsigned long len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17898 | assert(p != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17899 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17901 | if (get_object_struct(arr)->attributes & V7_OBJ_NOT_EXTENSIBLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17902 | if (is_strict_mode(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17903 | rcode = v7_throwf(v7, TYPE_ERROR, "Object is not extensible"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17904 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17907 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17908 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17910 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17911 | abuf = (struct mbuf *) malloc(sizeof(*abuf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17912 | mbuf_init(abuf, sizeof(val_t) * (index + 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17913 | p->value = v7_mk_foreign(v7, abuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17914 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17915 | len = abuf->len / sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17916 | /* TODO(mkm): possibly promote to sparse array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17917 | if (index > len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17918 | unsigned long i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17919 | val_t s = V7_TAG_NOVALUE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17920 | for (i = len; i < index; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17921 | mbuf_append(abuf, (char *) &s, sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17923 | len = index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17924 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17925 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17926 | if (index == len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17927 | mbuf_append(abuf, (char *) &v, sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17928 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17929 | memcpy(abuf->buf + index * sizeof(val_t), &v, sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17930 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17931 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17932 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17933 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17934 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17935 | struct v7_property *tmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17936 | rcode = set_property(v7, arr, buf, n, v, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17937 | ires = (tmp == NULL) ? -1 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17938 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17939 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17940 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17942 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17943 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17945 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 17946 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17947 | *res = ires; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17948 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17949 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17950 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17952 | void v7_array_del(struct v7 *v7, val_t arr, unsigned long index) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17953 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17954 | int n = v_sprintf_s(buf, sizeof(buf), "%lu", index); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17955 | v7_del(v7, arr, buf, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17956 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17957 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17958 | int v7_array_push(struct v7 *v7, v7_val_t arr, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17959 | return v7_array_set(v7, arr, v7_array_length(v7, arr), v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17960 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17961 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17962 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 17963 | enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v, |
Marko Mikulicic |
0:c0ecb8bf28eb | 17964 | int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17965 | return v7_array_set_throwing(v7, arr, v7_array_length(v7, arr), v, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17966 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17967 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 17968 | #line 1 "v7/src/object.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 17969 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 17970 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17971 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 17972 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 17973 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17975 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17976 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17977 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17978 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17979 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17980 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17981 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17982 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17983 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17984 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17985 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17986 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17987 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17989 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 17990 | * Default property attributes (see `v7_prop_attr_t`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 17991 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 17992 | #define V7_DEFAULT_PROPERTY_ATTRS 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 17993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 17994 | V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17995 | struct v7_generic_object *o = new_generic_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 17996 | if (o == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 17997 | return V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 17998 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 17999 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18000 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18001 | o->base.entity_id_base = V7_ENTITY_ID_PART_OBJ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18002 | o->base.entity_id_spec = V7_ENTITY_ID_PART_GEN_OBJ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18003 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18004 | o->base.properties = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18005 | obj_prototype_set(v7, &o->base, get_object_struct(prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18006 | return v7_object_to_value(&o->base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18009 | v7_val_t v7_mk_object(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18010 | return mk_object(v7, v7->vals.object_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18011 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18013 | V7_PRIVATE val_t v7_object_to_value(struct v7_object *o) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18014 | if (o == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18015 | return V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18016 | } else if (o->attributes & V7_OBJ_FUNCTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18017 | return pointer_to_value(o) | V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18018 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18019 | return pointer_to_value(o) | V7_TAG_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18020 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18021 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18022 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18023 | V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18024 | struct v7_generic_object *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18025 | if (v7_is_null(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18026 | ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18027 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18028 | assert(v7_is_generic_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18029 | ret = (struct v7_generic_object *) get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18030 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18031 | if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18032 | fprintf(stderr, "not a generic object!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18033 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18034 | } else if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_GEN_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18035 | fprintf(stderr, "not an object (but is a generic object)!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18036 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18038 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18040 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18041 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18042 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18043 | V7_PRIVATE struct v7_object *get_object_struct(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18044 | struct v7_object *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18045 | if (v7_is_null(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18046 | ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18047 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18048 | assert(v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18049 | ret = (struct v7_object *) get_ptr(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18050 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18051 | if (ret->entity_id_base != V7_ENTITY_ID_PART_OBJ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18052 | fprintf(stderr, "not an object!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18053 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18054 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18055 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18056 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18057 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18060 | int v7_is_object(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18061 | return (v & V7_TAG_MASK) == V7_TAG_OBJECT || |
Marko Mikulicic |
0:c0ecb8bf28eb | 18062 | (v & V7_TAG_MASK) == V7_TAG_FUNCTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18063 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18065 | V7_PRIVATE int v7_is_generic_object(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18066 | return (v & V7_TAG_MASK) == V7_TAG_OBJECT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18069 | /* Object properties {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18070 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18071 | V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18072 | struct v7_property *p = new_property(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18073 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18074 | p->entity_id = V7_ENTITY_ID_PROP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18075 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18076 | p->next = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18077 | p->name = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18078 | p->value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18079 | p->attributes = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18080 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18083 | V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18084 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18085 | size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18086 | v7_prop_attr_t attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18087 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18088 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18089 | val_t ss; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18090 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18091 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18093 | if (len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18094 | len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18095 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18097 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18098 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18099 | * len check is needed to allow getting the mbuf from the hidden property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18100 | * TODO(mkm): however hidden properties cannot be safely represented with |
Marko Mikulicic |
0:c0ecb8bf28eb | 18101 | * a zero length string anyway, so this will change. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18102 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18103 | if (o->attributes & V7_OBJ_DENSE_ARRAY && len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18104 | int ok, has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18105 | unsigned long i = cstr_to_ulong(name, len, &ok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18106 | if (ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18107 | v7->cur_dense_prop->value = v7_array_get2(v7, obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18108 | return has ? v7->cur_dense_prop : NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18109 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18110 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18112 | if (len <= 5) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18113 | ss = v7_mk_string(v7, name, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18114 | for (p = o->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18115 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18116 | if (p->entity_id != V7_ENTITY_ID_PROP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18117 | fprintf(stderr, "not a prop!=0x%x\n", p->entity_id); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18118 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18120 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18121 | if (p->name == ss && (attrs == 0 || (p->attributes & attrs))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18122 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18123 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18124 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18125 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18126 | for (p = o->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18127 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18128 | const char *s = v7_get_string(v7, &p->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18129 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18130 | if (p->entity_id != V7_ENTITY_ID_PROP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18131 | fprintf(stderr, "not a prop!=0x%x\n", p->entity_id); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18132 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18133 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18134 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18135 | if (n == len && strncmp(s, name, len) == 0 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18136 | (attrs == 0 || (p->attributes & attrs))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18137 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18138 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18139 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18140 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18141 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18142 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18144 | V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18145 | const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18146 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18147 | return v7_get_own_property2(v7, obj, name, len, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18148 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18150 | V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18151 | const char *name, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18152 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18153 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18155 | for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18156 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18157 | if ((prop = v7_get_own_property(v7, obj, name, len)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18158 | return prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18159 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18160 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18161 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18162 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18164 | V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18165 | v7_val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18166 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18167 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18168 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18169 | STATIC char buf[8]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18170 | const char *s = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18171 | uint8_t fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18173 | if (v7_is_string(name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18174 | s = v7_get_string(v7, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18175 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18176 | char *stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18177 | V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18178 | V7_STRINGIFY_DEFAULT, &stmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18179 | s = stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18180 | if (s != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18181 | fr = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18182 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18183 | name_len = strlen(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18184 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18186 | *res = v7_get_property(v7, obj, s, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18187 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18188 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18189 | if (fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18190 | free((void *) s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18191 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18192 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18193 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18195 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18196 | enum v7_err v7_get_throwing(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18197 | size_t name_len, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18198 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18199 | val_t v = obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18201 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18203 | if (name_len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18204 | name_len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18205 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18207 | if (v7_is_string(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18208 | v = v7->vals.string_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18209 | } else if (v7_is_number(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18210 | v = v7->vals.number_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18211 | } else if (v7_is_boolean(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18212 | v = v7->vals.boolean_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18213 | } else if (v7_is_undefined(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18214 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 18215 | v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of undefined", |
Marko Mikulicic |
0:c0ecb8bf28eb | 18216 | (int) name_len, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18217 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18218 | } else if (v7_is_null(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18219 | rcode = v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of null", |
Marko Mikulicic |
0:c0ecb8bf28eb | 18220 | (int) name_len, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18221 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18222 | } else if (is_cfunction_lite(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18223 | v = v7->vals.function_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18224 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18226 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18227 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18228 | struct v7_object *o = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18229 | if (v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18230 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18232 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18233 | if (o != NULL && (o->attributes & V7_OBJ_PROXY) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18234 | !is_special_proxy_name(name, name_len)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18235 | /* we need to access the target object through a proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18237 | val_t target_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18238 | val_t handler_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18239 | val_t name_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18240 | val_t get_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18241 | val_t get_args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18243 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18244 | * we need to create a copy of the name, because the given `name` might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18245 | * be returned by v7_get_string(), and any object creation might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18246 | * invalidate this pointer. Below, we're going to create some objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18247 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 18248 | * It would probably be cleaner to always create a copy before calling |
Marko Mikulicic |
0:c0ecb8bf28eb | 18249 | * v7_get_throwing if the name was returned by v7_get_string(), but that |
Marko Mikulicic |
0:c0ecb8bf28eb | 18250 | * would cause additional pressure on the heap, so let's not do that |
Marko Mikulicic |
0:c0ecb8bf28eb | 18251 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18252 | char *name_copy = (char *) calloc(1, name_len + 1 /* null-term */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18253 | memcpy(name_copy, name, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18255 | v7_own(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18256 | v7_own(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18257 | v7_own(v7, &name_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18258 | v7_own(v7, &get_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18259 | v7_own(v7, &get_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18261 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18262 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18263 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18264 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18265 | V7_TRY2(v7_get_throwing(v7, handler_v, "get", ~0, &get_v), clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18267 | if (v7_is_callable(v7, get_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18268 | /* The `get` callback is actually callable, so, use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18270 | /* prepare arguments for the callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18271 | get_args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18272 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18273 | * TODO(dfrank): don't copy string in case we already have val_t (we |
Marko Mikulicic |
0:c0ecb8bf28eb | 18274 | * need some generic function which will take both `const char *` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 18275 | * val_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18276 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18277 | v7_array_set(v7, get_args_v, 0, target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18278 | v7_array_set(v7, get_args_v, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18279 | v7_mk_string(v7, name_copy, name_len, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18280 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18281 | /* call `get` callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18282 | V7_TRY2(b_apply(v7, get_v, V7_UNDEFINED, get_args_v, 0, res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18283 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18284 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18285 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18286 | * there's no `get` callback: then, get property from the target object |
Marko Mikulicic |
0:c0ecb8bf28eb | 18287 | * (not from the proxy object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18288 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18289 | V7_TRY2(v7_get_throwing(v7, target_v, name_copy, name_len, res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18290 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18291 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18293 | clean_proxy: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18295 | free(name_copy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18297 | v7_disown(v7, &get_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18298 | v7_disown(v7, &get_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18299 | v7_disown(v7, &name_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18300 | v7_disown(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18301 | v7_disown(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18302 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18303 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18304 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18305 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18307 | /* regular (non-proxy) property access */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18308 | V7_TRY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18309 | v7_property_value(v7, obj, v7_get_property(v7, v, name, name_len), res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18311 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18312 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18313 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18314 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18316 | v7_val_t v7_get(struct v7 *v7, val_t obj, const char *name, size_t name_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18317 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18318 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18319 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18320 | v7_val_t ret = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18322 | rcode = v7_get_throwing(v7, obj, name, name_len, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18323 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18324 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18325 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18326 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18327 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18328 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18329 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18330 | ret = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18331 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18333 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18334 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18336 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18337 | V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18338 | v7_val_t name, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18339 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18340 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18341 | STATIC char buf[8]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18342 | const char *s = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18343 | uint8_t fr = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18345 | /* subscripting strings */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18346 | if (v7_is_string(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18347 | char ch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18348 | double dch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18350 | rcode = v7_char_code_at(v7, obj, name, &dch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18351 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18352 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18355 | if (!isnan(dch)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18356 | ch = dch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18357 | *res = v7_mk_string(v7, &ch, 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18358 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18359 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18361 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18362 | if (v7_is_string(name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18363 | s = v7_get_string(v7, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18364 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18365 | char *stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18366 | V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18367 | V7_STRINGIFY_DEFAULT, &stmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18368 | s = stmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18369 | if (s != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18370 | fr = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18371 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18372 | name_len = strlen(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18373 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18374 | V7_TRY(v7_get_throwing(v7, obj, s, name_len, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18376 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18377 | if (fr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18378 | free((void *) s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18380 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18381 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18383 | V7_PRIVATE void v7_destroy_property(struct v7_property **p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18384 | *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18385 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18387 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18388 | V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18389 | val_t obj, val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18390 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18391 | val_t setter = prop->value, args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18392 | v7_own(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18393 | args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18394 | v7_own(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18395 | if (prop->attributes & V7_PROPERTY_GETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18396 | setter = v7_array_get(v7, prop->value, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18397 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18398 | v7_array_set(v7, args, 0, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18399 | v7_disown(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18400 | v7_disown(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18401 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18402 | val_t val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18403 | V7_TRY(b_apply(v7, setter, obj, args, 0, &val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18404 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18406 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18407 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18408 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18409 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18410 | static v7_prop_attr_t apply_attrs_desc(v7_prop_attr_desc_t attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18411 | v7_prop_attr_t old_attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18412 | v7_prop_attr_t ret = old_attrs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18413 | if (old_attrs & V7_PROPERTY_NON_CONFIGURABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18414 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18415 | * The property is non-configurable: we can only change it from being |
Marko Mikulicic |
0:c0ecb8bf28eb | 18416 | * writable to non-writable |
Marko Mikulicic |
0:c0ecb8bf28eb | 18417 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18419 | if ((attrs_desc >> _V7_DESC_SHIFT) & V7_PROPERTY_NON_WRITABLE && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18420 | (attrs_desc & V7_PROPERTY_NON_WRITABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18421 | ret |= V7_PROPERTY_NON_WRITABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18422 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18424 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18425 | /* The property is configurable: we can change any attributes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18426 | ret = (old_attrs & ~(attrs_desc >> _V7_DESC_SHIFT)) | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18427 | (attrs_desc & _V7_DESC_MASK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18428 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18429 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18430 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18431 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18432 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18433 | int v7_def(struct v7 *v7, val_t obj, const char *name, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18434 | v7_prop_attr_desc_t attrs_desc, v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18435 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18436 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18437 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18438 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18440 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18441 | struct v7_property *tmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18442 | rcode = def_property(v7, obj, name, len, attrs_desc, val, 0 /*not assign*/, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18443 | &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18444 | ret = (tmp == NULL) ? -1 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18445 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18446 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18447 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18448 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18449 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18450 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18451 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18452 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18453 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18454 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18455 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18456 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18457 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18458 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18460 | int v7_set(struct v7 *v7, val_t obj, const char *name, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18461 | v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18462 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18463 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18464 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18465 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18467 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18468 | struct v7_property *tmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18469 | rcode = set_property(v7, obj, name, len, val, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18470 | ret = (tmp == NULL) ? -1 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18471 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18473 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18474 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18475 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18476 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18477 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18478 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18479 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18480 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18481 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18483 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18484 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18486 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18487 | V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18488 | val_t val, struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18489 | return def_property_v(v7, obj, name, 0, val, 1 /*as_assign*/, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18490 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18492 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18493 | V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18494 | size_t len, v7_val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18495 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18496 | return def_property(v7, obj, name, len, 0, val, 1 /*as_assign*/, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18499 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18500 | V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18501 | v7_prop_attr_desc_t attrs_desc, val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18502 | uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18503 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18504 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18505 | struct v7_property *prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18506 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18507 | const char *n = v7_get_string(v7, &name, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18509 | v7_own(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18510 | v7_own(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18512 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18513 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18514 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18517 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18518 | if ((get_object_struct(obj)->attributes & V7_OBJ_PROXY) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 18519 | !is_special_proxy_name(n, len)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18520 | /* we need to access the target object through a proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18521 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18522 | val_t target_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18523 | val_t handler_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18524 | val_t set_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18525 | val_t set_args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18527 | v7_own(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18528 | v7_own(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18529 | v7_own(v7, &set_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18530 | v7_own(v7, &set_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18532 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18533 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18534 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18535 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18536 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18537 | * We'll consult "set" property in case of the plain assignment only; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18538 | * Object.defineProperty() has its own trap `defineProperty` which is not |
Marko Mikulicic |
0:c0ecb8bf28eb | 18539 | * yet implemented in v7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 18540 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18541 | if (as_assign) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18542 | V7_TRY2(v7_get_throwing(v7, handler_v, "set", ~0, &set_v), clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18544 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18545 | if (v7_is_callable(v7, set_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18546 | /* The `set` callback is actually callable, so, use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18548 | /* prepare arguments for the callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18549 | set_args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18550 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18551 | * TODO(dfrank): don't copy string in case we already have val_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 18552 | * (we need some generic function which will take both const char * and |
Marko Mikulicic |
0:c0ecb8bf28eb | 18553 | * val_t for that) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18554 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18555 | v7_array_set(v7, set_args_v, 0, target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18556 | v7_array_set(v7, set_args_v, 1, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18557 | v7_array_set(v7, set_args_v, 2, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18558 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18559 | /* call `set` callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18560 | V7_TRY2(b_apply(v7, set_v, V7_UNDEFINED, set_args_v, 0, &val), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18561 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18563 | /* in strict mode, we should throw if trap returned falsy value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18564 | if (is_strict_mode(v7) && !v7_is_truthy(v7, val)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18565 | V7_THROW2( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18566 | v7_throwf(v7, TYPE_ERROR, "Trap returned falsy for property '%s'", |
Marko Mikulicic |
0:c0ecb8bf28eb | 18567 | v7_get_string(v7, &name, NULL)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18568 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18569 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18571 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18572 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18573 | * there's no `set` callback: then, set property on the target object |
Marko Mikulicic |
0:c0ecb8bf28eb | 18574 | * (not on the proxy object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 18575 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18576 | V7_TRY2( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18577 | def_property_v(v7, target_v, name, attrs_desc, val, as_assign, res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18578 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18579 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18580 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18581 | clean_proxy: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18582 | v7_disown(v7, &set_args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18583 | v7_disown(v7, &set_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18584 | v7_disown(v7, &handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18585 | v7_disown(v7, &target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18586 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18587 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18588 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18589 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18590 | /* regular (non-proxy) property access */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18591 | prop = v7_get_own_property(v7, obj, n, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18592 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18593 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18594 | * The own property with given `name` doesn't exist yet: try to create it, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18595 | * set requested `name` and `attributes`, and append to the object's |
Marko Mikulicic |
0:c0ecb8bf28eb | 18596 | * properties |
Marko Mikulicic |
0:c0ecb8bf28eb | 18597 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18599 | /* make sure the object is extensible */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18600 | if (get_object_struct(obj)->attributes & V7_OBJ_NOT_EXTENSIBLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18601 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18602 | * We should throw if we use `Object.defineProperty`, or if we're in |
Marko Mikulicic |
0:c0ecb8bf28eb | 18603 | * strict mode. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18604 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18605 | if (is_strict_mode(v7) || !as_assign) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18606 | V7_THROW(v7_throwf(v7, TYPE_ERROR, "Object is not extensible")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18607 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18608 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18609 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18610 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18612 | if ((prop = v7_mk_property(v7)) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18613 | prop = NULL; /* LCOV_EXCL_LINE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18614 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18615 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18616 | prop->name = name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18617 | prop->value = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18618 | prop->attributes = apply_attrs_desc(attrs_desc, V7_DEFAULT_PROPERTY_ATTRS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18620 | prop->next = get_object_struct(obj)->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18621 | get_object_struct(obj)->properties = prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18622 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18623 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18624 | /* Property already exists */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18626 | if (prop->attributes & V7_PROPERTY_NON_WRITABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18627 | /* The property is read-only */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18628 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18629 | if (as_assign) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18630 | /* Plain assignment: in strict mode throw, otherwise ignore */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18631 | if (is_strict_mode(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18632 | V7_THROW( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18633 | v7_throwf(v7, TYPE_ERROR, "Cannot assign to read-only property")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18634 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18635 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18636 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18637 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18638 | } else if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18639 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18640 | * Use `Object.defineProperty` semantic, and the property is |
Marko Mikulicic |
0:c0ecb8bf28eb | 18641 | * non-configurable: if no value is provided, or if new value is equal |
Marko Mikulicic |
0:c0ecb8bf28eb | 18642 | * to the existing one, then just fall through to change attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18643 | * otherwise, throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18644 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18645 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18646 | if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18647 | uint8_t equal = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18648 | if (v7_is_string(val) && v7_is_string(prop->value)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18649 | equal = (s_cmp(v7, val, prop->value) == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18650 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18651 | equal = (val == prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18652 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18654 | if (!equal) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18655 | /* Values are not equal: should throw */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18656 | V7_THROW(v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18657 | "Cannot redefine read-only property")); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18658 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18659 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18660 | * Values are equal. Will fall through so that attributes might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18661 | * change. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18662 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18663 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18664 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18665 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18666 | * No value is provided. Will fall through so that attributes might |
Marko Mikulicic |
0:c0ecb8bf28eb | 18667 | * change. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18668 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18669 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18670 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18671 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18672 | * Use `Object.defineProperty` semantic, and the property is |
Marko Mikulicic |
0:c0ecb8bf28eb | 18673 | * configurable: will fall through and assign new value, effectively |
Marko Mikulicic |
0:c0ecb8bf28eb | 18674 | * ignoring non-writable flag. This is the same as making a property |
Marko Mikulicic |
0:c0ecb8bf28eb | 18675 | * writable, then assigning a new value, and making a property |
Marko Mikulicic |
0:c0ecb8bf28eb | 18676 | * non-writable again. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18677 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18678 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18679 | } else if (prop->attributes & V7_PROPERTY_SETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18680 | /* Invoke setter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18681 | V7_TRY(v7_invoke_setter(v7, prop, obj, val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18682 | prop = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18683 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18686 | /* Set value and apply attrs delta */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18687 | if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18688 | prop->value = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18689 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18690 | prop->attributes = apply_attrs_desc(attrs_desc, prop->attributes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18691 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18693 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18694 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18695 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18696 | *res = prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18697 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18699 | v7_disown(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18700 | v7_disown(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18701 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18702 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18703 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18704 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18705 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18706 | V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18707 | size_t len, v7_prop_attr_desc_t attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18708 | v7_val_t val, uint8_t as_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18709 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18710 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18711 | val_t name_val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18713 | v7_own(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18714 | v7_own(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18715 | v7_own(v7, &name_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18716 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18717 | if (len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18718 | len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18719 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18721 | name_val = v7_mk_string(v7, name, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18722 | V7_TRY(def_property_v(v7, obj, name_val, attrs_desc, val, as_assign, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18723 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18724 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18725 | v7_disown(v7, &name_val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18726 | v7_disown(v7, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18727 | v7_disown(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18729 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18732 | V7_PRIVATE int set_method(struct v7 *v7, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18733 | v7_cfunction_t *func, int num_args) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18734 | return v7_def(v7, obj, name, strlen(name), V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18735 | mk_cfunction_obj(v7, func, num_args)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18736 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18737 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18738 | int v7_set_method(struct v7 *v7, v7_val_t obj, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18739 | v7_cfunction_t *func) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18740 | return set_method(v7, obj, name, func, ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18741 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18743 | V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18744 | v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18745 | return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18746 | v7_mk_cfunction(f)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18747 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18749 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18750 | * See comments in `object_public.h` |
Marko Mikulicic |
0:c0ecb8bf28eb | 18751 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18752 | int v7_del(struct v7 *v7, val_t obj, const char *name, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18753 | struct v7_property *prop, *prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18754 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18755 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18756 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18757 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18758 | if (len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18759 | len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18760 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18761 | for (prev = NULL, prop = get_object_struct(obj)->properties; prop != NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18762 | prev = prop, prop = prop->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18763 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18764 | const char *s = v7_get_string(v7, &prop->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18765 | if (n == len && strncmp(s, name, len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18766 | if (prev) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18767 | prev->next = prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18768 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18769 | get_object_struct(obj)->properties = prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18770 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18771 | v7_destroy_property(&prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18772 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18773 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18774 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18775 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18776 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18778 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18779 | V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18780 | struct v7_property *p, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18781 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18782 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18783 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18784 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18786 | if (p->attributes & V7_PROPERTY_GETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18787 | val_t getter = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18788 | if (p->attributes & V7_PROPERTY_SETTER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18789 | getter = v7_array_get(v7, p->value, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18790 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18791 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18792 | V7_TRY(b_apply(v7, getter, obj, V7_UNDEFINED, 0, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18793 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18794 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18797 | *res = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18798 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18799 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18800 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18801 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18802 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18804 | enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18805 | struct prop_iter_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18806 | return init_prop_iter_ctx(v7, obj, 1 /*proxy-transparent*/, ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18807 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18809 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18810 | V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18811 | int proxy_transp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18812 | struct prop_iter_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18813 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18815 | v7_own(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18817 | memset(ctx, 0x00, sizeof(*ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18818 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18819 | if (v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18820 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18821 | if (proxy_transp && get_object_struct(obj)->attributes & V7_OBJ_PROXY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18822 | v7_val_t ownKeys_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18823 | v7_val_t args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18824 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18825 | v7_own(v7, &ownKeys_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18826 | v7_own(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18828 | ctx->proxy_ctx = |
Marko Mikulicic |
0:c0ecb8bf28eb | 18829 | (struct prop_iter_proxy_ctx *) calloc(1, sizeof(*ctx->proxy_ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18830 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18831 | ctx->proxy_ctx->target_obj = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18832 | ctx->proxy_ctx->handler_obj = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18833 | ctx->proxy_ctx->own_keys = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18834 | ctx->proxy_ctx->get_own_prop_desc = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18836 | v7_own(v7, &ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18837 | v7_own(v7, &ctx->proxy_ctx->handler_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18838 | v7_own(v7, &ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18839 | v7_own(v7, &ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18841 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18842 | &ctx->proxy_ctx->target_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18843 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18844 | V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18845 | &ctx->proxy_ctx->handler_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18846 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18848 | V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "ownKeys", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18849 | &ownKeys_v), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18850 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18852 | if (v7_is_callable(v7, ownKeys_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18853 | /* prepare arguments for the ownKeys callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18854 | args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18855 | v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18856 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18857 | /* call `ownKeys` callback, and save the result in context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18858 | V7_TRY2(b_apply(v7, ownKeys_v, V7_UNDEFINED, args_v, 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18859 | &ctx->proxy_ctx->own_keys), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18860 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18861 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18862 | ctx->proxy_ctx->has_own_keys = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18863 | ctx->proxy_ctx->own_key_idx = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18864 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18865 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18866 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18867 | * No ownKeys callback, so we'll iterate real properties of the target |
Marko Mikulicic |
0:c0ecb8bf28eb | 18868 | * object |
Marko Mikulicic |
0:c0ecb8bf28eb | 18869 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18871 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18872 | * TODO(dfrank): add support for the target object which is a proxy as |
Marko Mikulicic |
0:c0ecb8bf28eb | 18873 | * well |
Marko Mikulicic |
0:c0ecb8bf28eb | 18874 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18875 | ctx->cur_prop = |
Marko Mikulicic |
0:c0ecb8bf28eb | 18876 | get_object_struct(ctx->proxy_ctx->target_obj)->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18879 | V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "_gpdc", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18880 | &ctx->proxy_ctx->get_own_prop_desc), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18881 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18882 | if (v7_is_foreign(ctx->proxy_ctx->get_own_prop_desc)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18883 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18884 | * C callback for getting property descriptor is provided: will use it |
Marko Mikulicic |
0:c0ecb8bf28eb | 18885 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18886 | ctx->proxy_ctx->has_get_own_prop_desc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18887 | ctx->proxy_ctx->has_get_own_prop_desc_C = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18888 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18889 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18890 | * No C callback for getting property descriptor is provided, let's |
Marko Mikulicic |
0:c0ecb8bf28eb | 18891 | * check if there is a JS one.. |
Marko Mikulicic |
0:c0ecb8bf28eb | 18892 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18893 | V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18894 | "getOwnPropertyDescriptor", ~0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18895 | &ctx->proxy_ctx->get_own_prop_desc), |
Marko Mikulicic |
0:c0ecb8bf28eb | 18896 | clean_proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18898 | if (v7_is_callable(v7, ctx->proxy_ctx->get_own_prop_desc)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18899 | /* Yes there is, we'll use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18900 | ctx->proxy_ctx->has_get_own_prop_desc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18901 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18902 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18904 | clean_proxy: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18905 | v7_disown(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18906 | v7_disown(v7, &ownKeys_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18907 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18908 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18909 | /* something went wrong, so, disown values in the context and free it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18910 | v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18911 | v7_disown(v7, &ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18912 | v7_disown(v7, &ctx->proxy_ctx->handler_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18913 | v7_disown(v7, &ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18914 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18915 | free(ctx->proxy_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18916 | ctx->proxy_ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18918 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18920 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18921 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 18922 | (void) proxy_transp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18923 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18925 | /* Object is not a proxy: we'll iterate real properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18926 | ctx->cur_prop = get_object_struct(obj)->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18928 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18929 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18930 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18931 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18933 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18934 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 18935 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18936 | v7_disown(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18937 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18938 | ctx->init = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18939 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18940 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18943 | void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18944 | if (ctx->init) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18945 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18946 | if (ctx->proxy_ctx != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18947 | v7_disown(v7, &ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18948 | v7_disown(v7, &ctx->proxy_ctx->handler_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18949 | v7_disown(v7, &ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18950 | v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18951 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18952 | free(ctx->proxy_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18953 | ctx->proxy_ctx = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18954 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 18955 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18956 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 18957 | ctx->init = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18958 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18959 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18961 | int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18962 | v7_val_t *value, v7_prop_attr_t *attrs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18963 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18964 | if (next_prop(v7, ctx, name, value, attrs, &ok) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18965 | fprintf(stderr, "next_prop failed\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18966 | ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18967 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18968 | return ok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 18970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18971 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 18972 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 18973 | static enum v7_err get_custom_prop_desc(struct v7 *v7, v7_val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18974 | struct prop_iter_ctx *ctx, |
Marko Mikulicic |
0:c0ecb8bf28eb | 18975 | struct v7_property *res_prop, int *ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18976 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18978 | v7_val_t args_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18979 | v7_val_t desc_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18980 | v7_val_t tmpflag_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18981 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18982 | v7_own(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18983 | v7_own(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18984 | v7_own(v7, &desc_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18985 | v7_own(v7, &tmpflag_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18987 | *ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18988 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18989 | if (ctx->proxy_ctx->has_get_own_prop_desc_C) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 18990 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 18991 | * There is a C callback which should fill the property descriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 18992 | * structure, see `v7_get_own_prop_desc_cb_t` |
Marko Mikulicic |
0:c0ecb8bf28eb | 18993 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 18994 | v7_get_own_prop_desc_cb_t *cb = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 18995 | memset(res_prop, 0, sizeof(*res_prop)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18996 | cb = (v7_get_own_prop_desc_cb_t *) v7_get_ptr( |
Marko Mikulicic |
0:c0ecb8bf28eb | 18997 | v7, ctx->proxy_ctx->get_own_prop_desc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 18998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 18999 | res_prop->attributes = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19000 | res_prop->value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19002 | *ok = !!cb(v7, ctx->proxy_ctx->target_obj, name, &res_prop->attributes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19003 | &res_prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19004 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19005 | /* prepare arguments for the getOwnPropertyDescriptor callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19006 | args_v = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19007 | v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19008 | v7_array_set(v7, args_v, 1, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19010 | /* call getOwnPropertyDescriptor callback */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19011 | V7_TRY(b_apply(v7, ctx->proxy_ctx->get_own_prop_desc, V7_UNDEFINED, args_v, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19012 | 0, &desc_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19014 | if (v7_is_object(desc_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19015 | res_prop->attributes = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19017 | V7_TRY(v7_get_throwing(v7, desc_v, "writable", ~0, &tmpflag_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19018 | if (!v7_is_truthy(v7, tmpflag_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19019 | res_prop->attributes |= V7_PROPERTY_NON_WRITABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19020 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19021 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19022 | V7_TRY(v7_get_throwing(v7, desc_v, "configurable", ~0, &tmpflag_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19023 | if (!v7_is_truthy(v7, tmpflag_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19024 | res_prop->attributes |= V7_PROPERTY_NON_CONFIGURABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19025 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19027 | V7_TRY(v7_get_throwing(v7, desc_v, "enumerable", ~0, &tmpflag_v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19028 | if (!v7_is_truthy(v7, tmpflag_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19029 | res_prop->attributes |= V7_PROPERTY_NON_ENUMERABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19030 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19031 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19032 | V7_TRY(v7_get_throwing(v7, desc_v, "value", ~0, &res_prop->value)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19033 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19034 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19035 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19036 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19037 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19038 | /* We always set the name in the property descriptor to the actual name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19039 | res_prop->name = name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19040 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19041 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19042 | v7_disown(v7, &tmpflag_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19043 | v7_disown(v7, &desc_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19044 | v7_disown(v7, &args_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19045 | v7_disown(v7, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19046 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19047 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19048 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19049 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19051 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19052 | V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19053 | v7_val_t *name, v7_val_t *value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19054 | v7_prop_attr_t *attrs, int *ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19055 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19056 | struct v7_property p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19058 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19059 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19060 | memset(&p, 0, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19061 | p.name = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19062 | p.value = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19063 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19064 | v7_own(v7, &p.name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19065 | v7_own(v7, &p.value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19066 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19067 | assert(ctx->init); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19069 | *ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19070 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19071 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 19072 | if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_own_keys) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19073 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19074 | * No `ownKeys` callback, so we'll iterate real properties of the object |
Marko Mikulicic |
0:c0ecb8bf28eb | 19075 | * (either the given object or, if it's a proxy, the proxy's target object) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19076 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19078 | if (ctx->cur_prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19079 | if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_get_own_prop_desc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19080 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19081 | * There is no `getOwnPropertyDescriptor` callback, so, use the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 19082 | * real property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19083 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19084 | memcpy(&p, ctx->cur_prop, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19085 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19086 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19087 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19088 | * There is a `getOwnPropertyDescriptor` callback, so call it for the |
Marko Mikulicic |
0:c0ecb8bf28eb | 19089 | * name of the current real property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19090 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19091 | V7_TRY(get_custom_prop_desc(v7, ctx->cur_prop->name, ctx, &p, ok)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19094 | ctx->cur_prop = ctx->cur_prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19095 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19096 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19097 | /* We have custom own keys */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19098 | v7_val_t cur_key = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19099 | size_t len = v7_array_length(v7, ctx->proxy_ctx->own_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19100 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19101 | v7_own(v7, &cur_key); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19103 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19104 | * Iterate through the custom own keys until we can get the proper property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19105 | * descriptor for the given key |
Marko Mikulicic |
0:c0ecb8bf28eb | 19106 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19107 | while (!*ok && (size_t) ctx->proxy_ctx->own_key_idx < len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19108 | cur_key = v7_array_get(v7, ctx->proxy_ctx->own_keys, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19109 | ctx->proxy_ctx->own_key_idx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19110 | ctx->proxy_ctx->own_key_idx++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19112 | if (ctx->proxy_ctx->has_get_own_prop_desc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19113 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19114 | * There is a `getOwnPropertyDescriptor` callback, so, call it for the |
Marko Mikulicic |
0:c0ecb8bf28eb | 19115 | * current custom key and get all descriptor data from the object |
Marko Mikulicic |
0:c0ecb8bf28eb | 19116 | * returned. The `ok` variable will be updated appropriately (it will |
Marko Mikulicic |
0:c0ecb8bf28eb | 19117 | * be 0 if the callback did not return a proper descriptor) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19118 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19119 | V7_TRY2(get_custom_prop_desc(v7, cur_key, ctx, &p, ok), clean_custom); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19120 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19121 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19122 | * There is no `getOwnPropertyDescriptor` callback, so, try to get |
Marko Mikulicic |
0:c0ecb8bf28eb | 19123 | * real property with the name equal to the current key |
Marko Mikulicic |
0:c0ecb8bf28eb | 19124 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19125 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19126 | const char *name = v7_get_string(v7, &cur_key, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19128 | struct v7_property *real_prop = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19129 | v7_get_own_property(v7, ctx->proxy_ctx->target_obj, name, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19130 | if (real_prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19131 | /* Property exists, so use data from its descriptor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19132 | memcpy(&p, real_prop, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19133 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19134 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19135 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19136 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19137 | clean_custom: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19138 | v7_disown(v7, &cur_key); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19139 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19140 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19142 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19144 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 19145 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19146 | * Proxy is disabled: just get the next property |
Marko Mikulicic |
0:c0ecb8bf28eb | 19147 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19148 | if (ctx->cur_prop != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19149 | memcpy(&p, ctx->cur_prop, sizeof(p)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19150 | *ok = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19151 | ctx->cur_prop = ctx->cur_prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19152 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19153 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19154 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19155 | /* If we have a valid property descriptor, use data from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19156 | if (*ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19157 | if (name != NULL) *name = p.name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19158 | if (value != NULL) *value = p.value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19159 | if (attrs != NULL) *attrs = p.attributes; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19160 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19162 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 19163 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19164 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19165 | v7_disown(v7, &p.value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19166 | v7_disown(v7, &p.name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19167 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19168 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19170 | /* }}} Object properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19172 | /* Object prototypes {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19173 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19174 | V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19175 | struct v7_object *proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19176 | int ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19177 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19178 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19179 | if (obj->attributes & V7_OBJ_FUNCTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19180 | ret = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19181 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19182 | ((struct v7_generic_object *) obj)->prototype = proto; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19183 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19184 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19185 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19186 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19187 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19189 | V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19190 | struct v7_object *obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19191 | if (obj->attributes & V7_OBJ_FUNCTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19192 | return get_object_struct(v7->vals.function_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19193 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19194 | return ((struct v7_generic_object *) obj)->prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19196 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19198 | V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19199 | if (!v7_is_object(o) || !v7_is_object(p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19200 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19203 | /* walk the prototype chain */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19204 | for (; !v7_is_null(o); o = v7_get_proto(v7, o)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19205 | if (v7_get_proto(v7, o) == p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19206 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19207 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19208 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19209 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19210 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19212 | int v7_is_instanceof(struct v7 *v7, val_t o, const char *c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19213 | return v7_is_instanceof_v(v7, o, v7_get(v7, v7->vals.global_object, c, ~0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19214 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19216 | int v7_is_instanceof_v(struct v7 *v7, val_t o, val_t c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19217 | return is_prototype_of(v7, o, v7_get(v7, c, "prototype", 9)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19218 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19220 | v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19221 | if (v7_is_generic_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19222 | v7_val_t old_proto = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19223 | v7_object_to_value(obj_prototype(v7, get_object_struct(obj))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19224 | obj_prototype_set(v7, get_object_struct(obj), get_object_struct(proto)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19225 | return old_proto; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19226 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19227 | return V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19228 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19229 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19230 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19231 | val_t v7_get_proto(struct v7 *v7, val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19232 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19233 | * NOTE: we don't use v7_is_callable() here, because it involves walking |
Marko Mikulicic |
0:c0ecb8bf28eb | 19234 | * through the object's properties, which may be expensive. And it's done |
Marko Mikulicic |
0:c0ecb8bf28eb | 19235 | * anyway for cfunction objects as it would for any other generic objects by |
Marko Mikulicic |
0:c0ecb8bf28eb | 19236 | * the call to `obj_prototype()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19237 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 19238 | * Since this function is called quite often (at least, GC walks the |
Marko Mikulicic |
0:c0ecb8bf28eb | 19239 | * prototype chain), it's better to just handle cfunction objects as generic |
Marko Mikulicic |
0:c0ecb8bf28eb | 19240 | * objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19241 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19242 | if (is_js_function(obj) || is_cfunction_lite(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19243 | return v7->vals.function_prototype; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19244 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19245 | return v7_object_to_value(obj_prototype(v7, get_object_struct(obj))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19246 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19248 | V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19249 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19250 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19251 | if (!v7_is_object(obj)) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19252 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19253 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19254 | for (p = o->properties; p != NULL; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19255 | if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19256 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19257 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19258 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19259 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19260 | return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19261 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19262 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19263 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19264 | * Returns the user data property structure associated with obj, or NULL if |
Marko Mikulicic |
0:c0ecb8bf28eb | 19265 | * `obj` is not an object. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19266 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19267 | static struct v7_property *get_or_create_user_data_property(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19268 | v7_val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19269 | struct v7_property *p = get_user_data_property(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19270 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19272 | if (p != NULL) return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19274 | if (!v7_is_object(obj)) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19275 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19276 | v7_own(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19277 | p = v7_mk_property(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19278 | v7_disown(v7, &obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19280 | p->attributes |= _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR | _V7_PROPERTY_HIDDEN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19282 | p->next = o->properties; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19283 | o->properties = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19285 | return p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19286 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19288 | void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19289 | struct v7_property *p = get_or_create_user_data_property(v7, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19290 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19291 | p->value = v7_mk_foreign(v7, ud); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19292 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19293 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19294 | void *v7_get_user_data(struct v7 *v7, v7_val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19295 | struct v7_property *p = get_user_data_property(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19296 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19297 | if (p == NULL) return NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19298 | return v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19299 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19300 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19301 | void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19302 | struct v7_property *p = get_or_create_user_data_property(v7, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19303 | struct v7_object *o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19304 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19305 | void *v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19306 | v7_destructor_cb_t *f; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19307 | } fu; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19309 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19311 | o = get_object_struct(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19312 | if (d != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19313 | o->attributes |= V7_OBJ_HAS_DESTRUCTOR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19314 | fu.f = d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19315 | p->name = v7_mk_foreign(v7, fu.v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19316 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19317 | o->attributes &= ~V7_OBJ_HAS_DESTRUCTOR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19318 | p->name = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19319 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19322 | /* }}} Object prototypes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19323 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 19324 | #line 1 "v7/src/regexp.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 19325 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19326 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19327 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 19328 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 19329 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19331 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19332 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19333 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19334 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19335 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19336 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19337 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19338 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19339 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19340 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 19341 | enum v7_err v7_mk_regexp(struct v7 *v7, const char *re, size_t re_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19342 | const char *flags, size_t flags_len, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19343 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19344 | struct slre_prog *p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19345 | struct v7_regexp *rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19347 | if (re_len == ~((size_t) 0)) re_len = strlen(re); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19348 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19349 | if (slre_compile(re, re_len, flags, flags_len, &p, 1) != SLRE_OK || |
Marko Mikulicic |
0:c0ecb8bf28eb | 19350 | p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19351 | rcode = v7_throwf(v7, TYPE_ERROR, "Invalid regex"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19352 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19353 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19354 | *res = mk_object(v7, v7->vals.regexp_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19355 | rp = (struct v7_regexp *) malloc(sizeof(*rp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19356 | rp->regexp_string = v7_mk_string(v7, re, re_len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19357 | v7_own(v7, &rp->regexp_string); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19358 | rp->compiled_regexp = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19359 | rp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19361 | v7_def(v7, *res, "", 0, _V7_DESC_HIDDEN(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 19362 | pointer_to_value(rp) | V7_TAG_REGEXP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19365 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19366 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19367 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19369 | V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19370 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19371 | int is = v7_is_regexp(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19372 | (void) is; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19373 | assert(is == 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19374 | /* TODO(mkm): make regexp use user data API */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19375 | p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19376 | assert(p != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19377 | return (struct v7_regexp *) get_ptr(p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19378 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19380 | int v7_is_regexp(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19381 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19382 | if (!v7_is_generic_object(v)) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19383 | /* TODO(mkm): make regexp use user data API */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19384 | p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19385 | if (p == NULL) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19386 | return (p->value & V7_TAG_MASK) == V7_TAG_REGEXP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19387 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19389 | V7_PRIVATE size_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 19390 | get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19391 | int re_flags = slre_get_flags(rp->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19392 | size_t n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19394 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19395 | if (re_flags & SLRE_FLAG_G) buf[n++] = 'g'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19396 | if (re_flags & SLRE_FLAG_I) buf[n++] = 'i'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19397 | if (re_flags & SLRE_FLAG_M) buf[n++] = 'm'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19398 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19399 | assert(n <= _V7_REGEXP_MAX_FLAGS_LEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19400 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19401 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19402 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19403 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19404 | #else /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19406 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19407 | * Dummy implementation when RegExp support is disabled: just return 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 19408 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19409 | int v7_is_regexp(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19410 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19411 | (void) v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19412 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19413 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19415 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19416 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 19417 | #line 1 "v7/src/exceptions.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 19418 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19419 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19420 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 19421 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 19422 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19424 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19425 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19426 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19427 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19428 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19429 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19430 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19432 | enum v7_err v7_throw(struct v7 *v7, v7_val_t val) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19433 | v7->vals.thrown_error = val; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19434 | v7->is_thrown = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19435 | return V7_EXEC_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19436 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19438 | void v7_clear_thrown_value(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19439 | v7->vals.thrown_error = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19440 | v7->is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19443 | enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19444 | ...) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19445 | /* TODO(dfrank) : get rid of v7->error_msg, allocate mem right here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19446 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19447 | va_list ap; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19448 | val_t e = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19449 | va_start(ap, err_fmt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19450 | c_vsnprintf(v7->error_msg, sizeof(v7->error_msg), err_fmt, ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19451 | va_end(ap); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19453 | v7_own(v7, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19454 | rcode = create_exception(v7, typ, v7->error_msg, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19455 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19456 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19457 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19458 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19459 | rcode = v7_throw(v7, e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19461 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19462 | v7_disown(v7, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19463 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19464 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19466 | enum v7_err v7_rethrow(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19467 | assert(v7->is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19468 | #ifdef NDEBUG |
Marko Mikulicic |
0:c0ecb8bf28eb | 19469 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19470 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19471 | return V7_EXEC_EXCEPTION; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19472 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19474 | v7_val_t v7_get_thrown_value(struct v7 *v7, uint8_t *is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19475 | if (is_thrown != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19476 | *is_thrown = v7->is_thrown; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19477 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19478 | return v7->vals.thrown_error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19479 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19481 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19482 | * Create an instance of the exception with type `typ` (see `TYPE_ERROR`, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19483 | * `SYNTAX_ERROR`, etc) and message `msg`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19484 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19485 | V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19486 | const char *msg, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19487 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19488 | uint8_t saved_creating_exception = v7->creating_exception; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19489 | val_t ctor_args = V7_UNDEFINED, ctor_func = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19490 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 19491 | assert(v7_is_undefined(v7->vals.thrown_error)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19492 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19494 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19495 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19496 | v7_own(v7, &ctor_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19497 | v7_own(v7, &ctor_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19499 | if (v7->creating_exception) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19500 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 19501 | fprintf(stderr, "Exception creation throws an exception %s: %s\n", typ, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19502 | msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19503 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19504 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19505 | v7->creating_exception = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19507 | /* Prepare arguments for the `Error` constructor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19508 | ctor_args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19509 | v7_array_set(v7, ctor_args, 0, v7_mk_string(v7, msg, strlen(msg), 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19511 | /* Get constructor for the given error `typ` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19512 | ctor_func = v7_get(v7, v7->vals.global_object, typ, ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19513 | if (v7_is_undefined(ctor_func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19514 | fprintf(stderr, "cannot find exception %s\n", typ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19517 | /* Create an error object, with prototype from constructor function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19518 | *res = mk_object(v7, v7_get(v7, ctor_func, "prototype", 9)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19519 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19520 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19521 | * Finally, call the error constructor, passing an error object as `this` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19522 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19523 | V7_TRY(b_apply(v7, ctor_func, *res, ctor_args, 0, NULL)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19525 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19526 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19527 | v7->creating_exception = saved_creating_exception; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19529 | v7_disown(v7, &ctor_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19530 | v7_disown(v7, &ctor_args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19532 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19533 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19534 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 19535 | #line 1 "v7/src/conversion.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 19536 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19537 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19538 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 19539 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 19540 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19542 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19543 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19544 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19545 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19546 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19547 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19548 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19549 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19550 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19551 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19552 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19553 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19554 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19555 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19557 | static void save_val(struct v7 *v7, const char *str, size_t str_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19558 | val_t *dst_v, char *dst, size_t dst_size, int wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19559 | size_t *res_wanted_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19560 | if (dst_v != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19561 | *dst_v = v7_mk_string(v7, str, str_len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19562 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19563 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19564 | if (dst != NULL && dst_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19565 | size_t size = str_len + 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19566 | if (size > dst_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19567 | size = dst_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19568 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19569 | memcpy(dst, str, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19571 | /* make sure we have null-term */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19572 | dst[dst_size - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19573 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19575 | if (res_wanted_len != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19576 | *res_wanted_len = (wanted_len >= 0) ? (size_t) wanted_len : str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19577 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19578 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19580 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19581 | V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19582 | char *buf, size_t buf_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19583 | size_t *res_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19584 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19585 | char tmp_buf[25]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19586 | double num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19587 | size_t wanted_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19589 | assert(!v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19591 | memset(tmp_buf, 0x00, sizeof(tmp_buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19593 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19594 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19595 | switch (val_type(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19596 | case V7_TYPE_STRING: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19597 | /* if `res` provided, set it to source value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19598 | if (res != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19599 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19600 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19601 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19602 | /* if buf provided, copy string data there */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19603 | if (buf != NULL && buf_size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19604 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19605 | const char *str = v7_get_string(v7, &v, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19606 | size += 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19607 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19608 | if (size > buf_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19609 | size = buf_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19610 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19612 | memcpy(buf, str, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19614 | /* make sure we have a null-term */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19615 | buf[buf_size - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19616 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19618 | if (res_len != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19619 | v7_get_string(v7, &v, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19620 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19621 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19622 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19623 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19624 | case V7_TYPE_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19625 | strncpy(tmp_buf, "null", 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 | case V7_TYPE_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19629 | strncpy(tmp_buf, "undefined", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19630 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19631 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19632 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19633 | if (v7_get_bool(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19634 | strncpy(tmp_buf, "true", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19635 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19636 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19637 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19638 | strncpy(tmp_buf, "false", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19639 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19640 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19642 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19643 | if (v == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19644 | strncpy(tmp_buf, "NaN", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19645 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19646 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19647 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19648 | num = v7_get_double(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19649 | if (isinf(num)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19650 | if (num < 0.0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19651 | strncpy(tmp_buf, "-Infinity", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19652 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19653 | strncpy(tmp_buf, "Infinity", sizeof(tmp_buf) - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19654 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19655 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19656 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19657 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19658 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19659 | const char *fmt = num > 1e10 ? "%.21g" : "%.10g"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19660 | wanted_len = snprintf(tmp_buf, sizeof(tmp_buf), fmt, num); |
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 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19665 | case V7_TYPE_CFUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19666 | #ifdef V7_UNIT_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 19667 | wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_xxxxxx"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19668 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19669 | res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19670 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19671 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 19672 | wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_%p", get_ptr(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19673 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19674 | res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19675 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19676 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 19677 | case V7_TYPE_FOREIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19678 | wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "[foreign_%p]", |
Marko Mikulicic |
0:c0ecb8bf28eb | 19679 | v7_get_ptr(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19680 | save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19681 | res_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19682 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19683 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19684 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19685 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19687 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19689 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19690 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19691 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19693 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19694 | V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19695 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19697 | assert(!v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19699 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19701 | if (v7_is_number(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19702 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19703 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19704 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19705 | if (v7_is_undefined(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19706 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19707 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19708 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19710 | if (v7_is_null(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19711 | *res = v7_mk_number(v7, 0.0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19712 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19713 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19714 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19715 | if (v7_is_boolean(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19716 | *res = v7_mk_number(v7, !!v7_get_bool(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19717 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19718 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19719 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19720 | if (is_cfunction_lite(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19721 | *res = v7_mk_number(v7, 0.0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19722 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19723 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19725 | if (v7_is_string(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19726 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19727 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19728 | char *e, *s = (char *) v7_get_string(v7, res, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19729 | if (n != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19730 | d = cs_strtod(s, &e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19731 | if (e - n != s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19732 | d = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19733 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19734 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19735 | /* empty string: convert to 0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19736 | d = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19737 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19738 | *res = v7_mk_number(v7, d); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19739 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19740 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19741 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19742 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19743 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19744 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19745 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19746 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19748 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19749 | enum v7_err to_primitive(struct v7 *v7, val_t v, enum to_primitive_hint hint, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19750 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19751 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19752 | enum v7_err (*p_func)(struct v7 *v7, val_t v, val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19754 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19756 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19758 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19759 | * If given value is an object, try to convert it to string by calling first |
Marko Mikulicic |
0:c0ecb8bf28eb | 19760 | * preferred function (`toString()` or `valueOf()`, depending on the `hint` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19761 | * argument) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19762 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19763 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19764 | /* Handle special case for Date object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19765 | if (hint == V7_TO_PRIMITIVE_HINT_AUTO) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19766 | hint = (v7_get_proto(v7, *res) == v7->vals.date_prototype) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19767 | ? V7_TO_PRIMITIVE_HINT_STRING |
Marko Mikulicic |
0:c0ecb8bf28eb | 19768 | : V7_TO_PRIMITIVE_HINT_NUMBER; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19769 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19770 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19771 | p_func = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19772 | (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_value_of : obj_to_string; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19773 | rcode = p_func(v7, *res, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19774 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19775 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19776 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19777 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19778 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19779 | * If returned value is still an object, get original argument value |
Marko Mikulicic |
0:c0ecb8bf28eb | 19780 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19781 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19782 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19783 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19784 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19786 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19787 | * If the value is still an object, try to call second function (`valueOf()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19788 | * or `toString()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 19789 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19790 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19791 | p_func = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19792 | (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_to_string : obj_value_of; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19793 | rcode = p_func(v7, *res, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19794 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19795 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19796 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19797 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19799 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19800 | * If the value is still an object, then throw. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19801 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19802 | if (v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19803 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 19804 | v7_throwf(v7, TYPE_ERROR, "Cannot convert object to primitive value"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19805 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19806 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19808 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19809 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19810 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19811 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19813 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19814 | V7_PRIVATE enum v7_err to_string(struct v7 *v7, val_t v, val_t *res, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19815 | size_t buf_size, size_t *res_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19816 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19817 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19818 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19819 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19820 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19821 | * Convert value to primitive if needed, calling `toString()` first |
Marko Mikulicic |
0:c0ecb8bf28eb | 19822 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19823 | V7_TRY(to_primitive(v7, v, V7_TO_PRIMITIVE_HINT_STRING, &v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19824 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19825 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19826 | * Now, we're guaranteed to have a primitive here. Convert it to string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19827 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19828 | V7_TRY(primitive_to_str(v7, v, res, buf, buf_size, res_len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19830 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19831 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19832 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19833 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19835 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19836 | V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19837 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19839 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19841 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19842 | * Convert value to primitive if needed, calling `valueOf()` first |
Marko Mikulicic |
0:c0ecb8bf28eb | 19843 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19844 | rcode = to_primitive(v7, *res, V7_TO_PRIMITIVE_HINT_NUMBER, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19845 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19846 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19849 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19850 | * Now, we're guaranteed to have a primitive here. Convert it to number. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19851 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19852 | rcode = primitive_to_number(v7, *res, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19853 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19854 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19855 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19856 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19857 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19858 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19859 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19861 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19862 | V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19863 | long *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19864 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19865 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19867 | /* if value is `undefined`, just return `default_value` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19868 | if (v7_is_undefined(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19869 | *res = default_value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19870 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19871 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19873 | /* Try to convert value to number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19874 | rcode = to_number_v(v7, v, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19875 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19876 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19879 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19880 | * Conversion to number succeeded, so, convert it to long |
Marko Mikulicic |
0:c0ecb8bf28eb | 19881 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19882 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19883 | d = v7_get_double(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19884 | /* We want to return LONG_MAX if d is positive Inf, thus d < 0 check */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19885 | if (isnan(d) || (isinf(d) && d < 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19886 | *res = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19887 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19888 | } else if (d > LONG_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19889 | *res = LONG_MAX; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19890 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19892 | *res = (long) d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19893 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19894 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19895 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19896 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19897 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19899 | V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19900 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19901 | val_t func_valueOf = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19903 | v7_own(v7, &func_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19904 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19906 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19907 | * TODO(dfrank): use `assert(v7_is_object(v))` instead, like `obj_to_string()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 19908 | * does, and fix all callers to ensure it's an object before calling. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19909 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 19910 | * Or, conversely, make `obj_to_string()` to accept objects. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19911 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19912 | if (!v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19913 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19914 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19917 | V7_TRY(v7_get_throwing(v7, v, "valueOf", 7, &func_valueOf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19918 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19919 | if (v7_is_callable(v7, func_valueOf)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19920 | V7_TRY(b_apply(v7, func_valueOf, v, V7_UNDEFINED, 0, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19921 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19923 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19924 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19925 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19926 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19927 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19928 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19929 | v7_disown(v7, &func_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19931 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19932 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19934 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19935 | * Caller should ensure that `v` is an object |
Marko Mikulicic |
0:c0ecb8bf28eb | 19936 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19937 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 19938 | V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19939 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19940 | val_t to_string_func = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19942 | /* Caller should ensure that `v` is an object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19943 | assert(v7_is_object(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19945 | v7_own(v7, &to_string_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19946 | v7_own(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19947 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19948 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19949 | * If `toString` is callable, then call it; otherwise, just return source |
Marko Mikulicic |
0:c0ecb8bf28eb | 19950 | * value |
Marko Mikulicic |
0:c0ecb8bf28eb | 19951 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19952 | V7_TRY(v7_get_throwing(v7, v, "toString", 8, &to_string_func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19953 | if (v7_is_callable(v7, to_string_func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19954 | V7_TRY(b_apply(v7, to_string_func, v, V7_UNDEFINED, 0, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19955 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19956 | *res = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19957 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19959 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19960 | v7_disown(v7, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19961 | v7_disown(v7, &to_string_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 19962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19963 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19964 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19965 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19966 | static const char *hex_digits = "0123456789abcdef"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19967 | static char *append_hex(char *buf, char *limit, uint8_t c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19968 | if (buf < limit) *buf++ = 'u'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19969 | if (buf < limit) *buf++ = '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19970 | if (buf < limit) *buf++ = '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19971 | if (buf < limit) *buf++ = hex_digits[(int) ((c >> 4) % 0xf)]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19972 | if (buf < limit) *buf++ = hex_digits[(int) (c & 0xf)]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19973 | return buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19974 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 19975 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19976 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19977 | * Appends quoted s to buf. Any double quote contained in s will be escaped. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19978 | * Returns the number of characters that would have been added, |
Marko Mikulicic |
0:c0ecb8bf28eb | 19979 | * like snprintf. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19980 | * If size is zero it doesn't output anything but keeps counting. |
Marko Mikulicic |
0:c0ecb8bf28eb | 19981 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19982 | static int snquote(char *buf, size_t size, const char *s, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 19983 | char *limit = buf + size - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19984 | const char *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19985 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 19986 | * String single character escape sequence: |
Marko Mikulicic |
0:c0ecb8bf28eb | 19987 | * http://www.ecma-international.org/ecma-262/6.0/index.html#table-34 |
Marko Mikulicic |
0:c0ecb8bf28eb | 19988 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 19989 | * 0x8 -> \b |
Marko Mikulicic |
0:c0ecb8bf28eb | 19990 | * 0x9 -> \t |
Marko Mikulicic |
0:c0ecb8bf28eb | 19991 | * 0xa -> \n |
Marko Mikulicic |
0:c0ecb8bf28eb | 19992 | * 0xb -> \v |
Marko Mikulicic |
0:c0ecb8bf28eb | 19993 | * 0xc -> \f |
Marko Mikulicic |
0:c0ecb8bf28eb | 19994 | * 0xd -> \r |
Marko Mikulicic |
0:c0ecb8bf28eb | 19995 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 19996 | const char *specials = "btnvfr"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19997 | size_t i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 19998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 19999 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20000 | if (buf < limit) *buf++ = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20002 | for (end = s + len; s < end; s++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20003 | if (*s == '"' || *s == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20004 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20005 | if (buf < limit) *buf++ = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20006 | } else if (*s >= '\b' && *s <= '\r') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20007 | i += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20008 | if (buf < limit) *buf++ = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20009 | if (buf < limit) *buf++ = specials[*s - '\b']; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20010 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20011 | } else if ((unsigned char) *s < '\b' || (*s > '\r' && *s < ' ')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20012 | i += 6 /* \uXXXX */; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20013 | if (buf < limit) *buf++ = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20014 | buf = append_hex(buf, limit, (uint8_t) *s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20015 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20016 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20017 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20018 | if (buf < limit) *buf++ = *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20019 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20021 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20022 | if (buf < limit) *buf++ = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20024 | if (size != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20025 | *buf = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20027 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20028 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20029 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20030 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20031 | * Returns whether the value of given type should be skipped when generating |
Marko Mikulicic |
0:c0ecb8bf28eb | 20032 | * JSON output |
Marko Mikulicic |
0:c0ecb8bf28eb | 20033 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20034 | static int should_skip_for_json(enum v7_type type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20035 | int ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20036 | switch (type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20037 | /* All permitted values */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20038 | case V7_TYPE_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20039 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20040 | case V7_TYPE_BOOLEAN_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20041 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20042 | case V7_TYPE_NUMBER_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20043 | case V7_TYPE_STRING: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20044 | case V7_TYPE_STRING_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20045 | case V7_TYPE_GENERIC_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20046 | case V7_TYPE_ARRAY_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20047 | case V7_TYPE_DATE_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20048 | case V7_TYPE_REGEXP_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20049 | case V7_TYPE_ERROR_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20050 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20051 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20052 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20053 | ret = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20054 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20055 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20056 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20057 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20059 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 20060 | V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20061 | size_t size, size_t *res_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20062 | uint8_t is_debug) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20063 | val_t el; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20064 | char *vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20065 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20066 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20067 | struct gc_tmp_frame tf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20069 | tmp_stack_push(&tf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20070 | tmp_stack_push(&tf, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20071 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20072 | * TODO(dfrank) : also push all `v7_val_t`s that are declared below |
Marko Mikulicic |
0:c0ecb8bf28eb | 20073 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20074 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20075 | if (size > 0) *buf = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20076 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20077 | if (!is_debug && should_skip_for_json(val_type(v7, v))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20078 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20079 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20080 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20081 | for (vp = v7->json_visited_stack.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20082 | vp < v7->json_visited_stack.buf + v7->json_visited_stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20083 | vp += sizeof(val_t)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20084 | if (*(val_t *) vp == v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20085 | strncpy(buf, "[Circular]", size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20086 | len = 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20087 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20089 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20091 | switch (val_type(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20092 | case V7_TYPE_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20093 | case V7_TYPE_BOOLEAN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20094 | case V7_TYPE_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20095 | case V7_TYPE_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20096 | case V7_TYPE_CFUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20097 | case V7_TYPE_FOREIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20098 | /* For those types, regular `primitive_to_str()` works */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20099 | V7_TRY(primitive_to_str(v7, v, NULL, buf, size, &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20100 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20102 | case V7_TYPE_STRING: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20103 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20104 | * For strings we can't just use `primitive_to_str()`, because we need |
Marko Mikulicic |
0:c0ecb8bf28eb | 20105 | * quoted value |
Marko Mikulicic |
0:c0ecb8bf28eb | 20106 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20107 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20108 | const char *str = v7_get_string(v7, &v, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20109 | len = snquote(buf, size, str, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20110 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20113 | case V7_TYPE_DATE_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20114 | v7_val_t func = V7_UNDEFINED, val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20115 | V7_TRY(v7_get_throwing(v7, v, "toString", 8, &func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20116 | #if V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 20117 | if (!is_debug) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20118 | V7_TRY(v7_get_throwing(v7, v, "toJSON", 6, &func)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20120 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20121 | V7_TRY(b_apply(v7, func, v, V7_UNDEFINED, 0, &val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20122 | V7_TRY(to_json_or_debug(v7, val, buf, size, &len, is_debug)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20123 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20124 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20125 | case V7_TYPE_GENERIC_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20126 | case V7_TYPE_BOOLEAN_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20127 | case V7_TYPE_STRING_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20128 | case V7_TYPE_NUMBER_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20129 | case V7_TYPE_REGEXP_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20130 | case V7_TYPE_ERROR_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20131 | /* TODO(imax): make it return the desired size of the buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20132 | char *b = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20133 | v7_val_t name = V7_UNDEFINED, val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20134 | v7_prop_attr_t attrs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20135 | const char *pname; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20136 | size_t nlen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20137 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20138 | struct prop_iter_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20139 | memset(&ctx, 0, sizeof(ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20140 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20141 | mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20142 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "{"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20143 | V7_TRY2(init_prop_iter_ctx(v7, v, 1 /*proxy-transparent*/, &ctx), |
Marko Mikulicic |
0:c0ecb8bf28eb | 20144 | clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20145 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20146 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20147 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20148 | V7_TRY2(next_prop(v7, &ctx, &name, &val, &attrs, &ok), clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20149 | if (!ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20150 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20151 | } else if (attrs & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20152 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20153 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20154 | pname = v7_get_string(v7, &name, &nlen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20155 | V7_TRY(v7_get_throwing(v7, v, pname, nlen, &val)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20156 | if (!is_debug && should_skip_for_json(val_type(v7, val))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20157 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20158 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20159 | if (b - buf != 1) { /* Not the first property to be printed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20160 | b += c_snprintf(b, BUF_LEFT(size, b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20161 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20162 | s = v7_get_string(v7, &name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20163 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "\"%.*s\":", (int) n, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20164 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20165 | size_t tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20166 | V7_TRY2(to_json_or_debug(v7, val, b, BUF_LEFT(size, b - buf), &tmp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20167 | is_debug), |
Marko Mikulicic |
0:c0ecb8bf28eb | 20168 | clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20169 | b += tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20170 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20171 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20172 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20173 | v7->json_visited_stack.len -= sizeof(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20175 | clean_iter: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20176 | v7_destruct_prop_iter_ctx(v7, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20177 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20178 | len = b - buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20179 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20180 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20181 | case V7_TYPE_ARRAY_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20182 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20183 | char *b = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20184 | size_t i, alen = v7_array_length(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20185 | mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20186 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "["); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20187 | for (i = 0; i < alen; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20188 | el = v7_array_get2(v7, v, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20189 | if (has) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20190 | size_t tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20191 | if (!is_debug && should_skip_for_json(val_type(v7, el))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20192 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "null"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20193 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20194 | V7_TRY(to_json_or_debug(v7, el, b, BUF_LEFT(size, b - buf), &tmp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20195 | is_debug)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20196 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20197 | b += tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20198 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20199 | if (i != alen - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20200 | b += c_snprintf(b, BUF_LEFT(size, b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20202 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20203 | b += c_snprintf(b, BUF_LEFT(size, b - buf), "]"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20204 | v7->json_visited_stack.len -= sizeof(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20205 | len = b - buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20206 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20207 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20208 | case V7_TYPE_CFUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20209 | V7_TRY(obj_value_of(v7, v, &v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20210 | len = c_snprintf(buf, size, "Function cfunc_%p", get_ptr(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20211 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20212 | case V7_TYPE_FUNCTION_OBJECT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20213 | V7_TRY(to_string(v7, v, NULL, buf, size, &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20214 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20216 | case V7_TYPE_MAX_OBJECT_TYPE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20217 | case V7_NUM_TYPES: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20218 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20219 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20220 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20221 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20223 | len = 0; /* for compilers that don't know about abort() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20224 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20226 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20227 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20228 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20229 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20230 | if (res_len != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20231 | *res_len = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20232 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20233 | tmp_frame_cleanup(&tf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20234 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20235 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20237 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 20238 | V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20239 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20240 | int is_truthy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20242 | is_truthy = ((v7_is_boolean(v) && v7_get_bool(v7, v)) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20243 | (v7_is_number(v) && v7_get_double(v7, v) != 0.0) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20244 | (v7_is_string(v) && v7_get_string(v7, &v, &len) && len > 0) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20245 | (v7_is_object(v))) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 20246 | v != V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20247 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20248 | return v7_mk_boolean(v7, is_truthy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20251 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20252 | * v7_stringify allocates a new buffer if value representation doesn't fit into |
Marko Mikulicic |
0:c0ecb8bf28eb | 20253 | * buf. Caller is responsible for freeing that buffer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20254 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20255 | char *v7_stringify(struct v7 *v7, val_t v, char *buf, size_t size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20256 | enum v7_stringify_mode mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20257 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20258 | uint8_t saved_is_thrown = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20259 | val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20260 | char *ret = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20262 | rcode = v7_stringify_throwing(v7, v, buf, size, mode, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20263 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20264 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20265 | if (saved_is_thrown) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20266 | rcode = v7_throw(v7, saved_thrown); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20267 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20268 | v7_clear_thrown_value(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20271 | buf[0] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20272 | ret = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20273 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20275 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20276 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20278 | enum v7_err v7_stringify_throwing(struct v7 *v7, val_t v, char *buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20279 | size_t size, enum v7_stringify_mode mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20280 | char **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20281 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20282 | char *p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20283 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20285 | switch (mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20286 | case V7_STRINGIFY_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20287 | V7_TRY(to_string(v7, v, NULL, buf, size, &len)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20288 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20289 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20290 | case V7_STRINGIFY_JSON: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20291 | V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20292 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20293 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20294 | case V7_STRINGIFY_DEBUG: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20295 | V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20296 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20297 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20298 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20299 | /* fit null terminating byte */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20300 | if (len >= size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20301 | /* Buffer is not large enough. Allocate a bigger one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20302 | p = (char *) malloc(len + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20303 | V7_TRY(v7_stringify_throwing(v7, v, p, len + 1, mode, res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20304 | assert(*res == p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20305 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20306 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20307 | *res = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20308 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20309 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20311 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20312 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20313 | * If we're going to throw, and we allocated a buffer, then free it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20314 | * But if we don't throw, then the caller will free it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20315 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20316 | if (rcode != V7_OK && p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20317 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20318 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20319 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20322 | int v7_is_truthy(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20323 | return v7_get_bool(v7, to_boolean_v(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20324 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20325 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 20326 | #line 1 "v7/src/shdata.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 20327 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20328 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20329 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 20330 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 20331 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20333 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20334 | /* Amalgamated: #include "v7/src/shdata.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20335 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20336 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 20337 | V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20338 | struct shdata *ret = |
Marko Mikulicic |
0:c0ecb8bf28eb | 20339 | (struct shdata *) calloc(1, sizeof(struct shdata) + size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20340 | shdata_retain(ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20341 | if (payload != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20342 | memcpy((char *) shdata_get_payload(ret), (char *) payload, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20343 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20344 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20345 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20347 | V7_PRIVATE struct shdata *shdata_create_from_string(const char *src) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20348 | return shdata_create(src, strlen(src) + 1 /*null-term*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20349 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20351 | V7_PRIVATE void shdata_retain(struct shdata *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20352 | p->refcnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20353 | assert(p->refcnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20354 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20356 | V7_PRIVATE void shdata_release(struct shdata *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20357 | assert(p->refcnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20358 | p->refcnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20359 | if (p->refcnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20360 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20361 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20362 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20364 | V7_PRIVATE void *shdata_get_payload(struct shdata *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20365 | return (char *) p + sizeof(*p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20366 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20367 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20368 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 20369 | #line 1 "v7/src/gc.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 20370 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20371 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20372 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 20373 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 20374 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20376 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20377 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20378 | /* Amalgamated: #include "v7/src/varint.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20379 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20380 | /* Amalgamated: #include "v7/src/freeze.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20381 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20382 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20383 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20384 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20385 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20386 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20387 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20388 | /* Amalgamated: #include "v7/src/heapusage.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20390 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 20391 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20392 | #ifdef V7_STACK_GUARD_MIN_SIZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20393 | void *v7_sp_limit = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20394 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20396 | void gc_mark_string(struct v7 *, val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20398 | static struct gc_block *gc_new_block(struct gc_arena *a, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20399 | static void gc_free_block(struct gc_block *b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20400 | static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20401 | static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20402 | static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20403 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20404 | V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20405 | return (struct v7_generic_object *) gc_alloc_cell(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20406 | &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20409 | V7_PRIVATE struct v7_property *new_property(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20410 | return (struct v7_property *) gc_alloc_cell(v7, &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20411 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20412 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20413 | V7_PRIVATE struct v7_js_function *new_function(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20414 | return (struct v7_js_function *) gc_alloc_cell(v7, &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20415 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20417 | V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20418 | struct gc_tmp_frame frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20419 | frame.v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20420 | frame.pos = v7->tmp_stack.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20421 | return frame; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20422 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20424 | V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *tf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20425 | tf->v7->tmp_stack.len = tf->pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20428 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20429 | * TODO(mkm): perhaps it's safer to keep val_t in the temporary |
Marko Mikulicic |
0:c0ecb8bf28eb | 20430 | * roots stack, instead of keeping val_t*, in order to be better |
Marko Mikulicic |
0:c0ecb8bf28eb | 20431 | * able to debug the relocating GC. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20432 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20433 | V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *tf, val_t *vp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20434 | mbuf_append(&tf->v7->tmp_stack, (char *) &vp, sizeof(val_t *)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20435 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20436 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20437 | /* Initializes a new arena. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20438 | V7_PRIVATE void gc_arena_init(struct gc_arena *a, size_t cell_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20439 | size_t initial_size, size_t size_increment, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20440 | const char *name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20441 | assert(cell_size >= sizeof(uintptr_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20443 | memset(a, 0, sizeof(*a)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20444 | a->cell_size = cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20445 | a->name = name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20446 | a->size_increment = size_increment; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20447 | a->blocks = gc_new_block(a, initial_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20448 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20450 | V7_PRIVATE void gc_arena_destroy(struct v7 *v7, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20451 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20453 | if (a->blocks != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20454 | gc_sweep(v7, a, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20455 | for (b = a->blocks; b != NULL;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20456 | struct gc_block *tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20457 | tmp = b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20458 | b = b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20459 | gc_free_block(tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20462 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20464 | static void gc_free_block(struct gc_block *b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20465 | free(b->base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20466 | free(b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20467 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20469 | static struct gc_block *gc_new_block(struct gc_arena *a, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20470 | struct gc_cell *cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20471 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20473 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20474 | b = (struct gc_block *) calloc(1, sizeof(*b)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20475 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20476 | if (b == NULL) abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20478 | b->size = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20479 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20480 | b->base = (struct gc_cell *) calloc(a->cell_size, b->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20481 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20482 | if (b->base == NULL) abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20484 | for (cur = GC_CELL_OP(a, b->base, +, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20485 | cur < GC_CELL_OP(a, b->base, +, b->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20486 | cur = GC_CELL_OP(a, cur, +, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20487 | cur->head.link = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20488 | a->free = cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20489 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20491 | return b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20492 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20494 | V7_PRIVATE void *gc_alloc_cell(struct v7 *v7, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20495 | #if V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 20496 | struct gc_cell *r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20497 | maybe_gc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20498 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20499 | r = (struct gc_cell *) calloc(1, a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20500 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20501 | mbuf_append(&v7->malloc_trace, &r, sizeof(r)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20502 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20503 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 20504 | struct gc_cell *r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20505 | if (a->free == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20506 | if (!maybe_gc(v7)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20507 | /* GC is inhibited, so, schedule invocation for later */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20508 | v7->need_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20509 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20511 | if (a->free == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20512 | struct gc_block *b = gc_new_block(a, a->size_increment); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20513 | b->next = a->blocks; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20514 | a->blocks = b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20516 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20517 | r = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20519 | UNMARK(r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20521 | a->free = r->head.link; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20523 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20524 | a->allocations++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20525 | a->alive++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20526 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20528 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20529 | * TODO(mkm): minor opt possible since most of the fields |
Marko Mikulicic |
0:c0ecb8bf28eb | 20530 | * are overwritten downstream, but not worth the yak shave time |
Marko Mikulicic |
0:c0ecb8bf28eb | 20531 | * when fields are added to GC-able structures */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20532 | memset(r, 0, a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20533 | return (void *) r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20534 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20535 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20536 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20537 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 20538 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20539 | * Scans trough the memory blocks registered in the malloc trace. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20540 | * Free the unmarked ones and reset the mark on the rest. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20541 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20542 | void gc_sweep_malloc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20543 | struct gc_cell **cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20544 | for (cur = (struct gc_cell **) v7->malloc_trace.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20545 | cur < (struct gc_cell **) (v7->malloc_trace.buf + v7->malloc_trace.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20546 | cur++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20547 | if (*cur == NULL) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20548 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20549 | if (MARKED(*cur)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20550 | UNMARK(*cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20551 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20552 | free(*cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20553 | /* TODO(mkm): compact malloc trace buffer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20554 | *cur = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20555 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20556 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20557 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20558 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20560 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20561 | * Scans the arena and add all unmarked cells to the free list. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20562 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20563 | * Empty blocks get deallocated. The head of the free list will contais cells |
Marko Mikulicic |
0:c0ecb8bf28eb | 20564 | * from the last (oldest) block. Cells will thus be allocated in block order. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20565 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20566 | void gc_sweep(struct v7 *v7, struct gc_arena *a, size_t start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20567 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20568 | struct gc_cell *cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20569 | struct gc_block **prevp = &a->blocks; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20570 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20571 | a->alive = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20572 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20574 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20575 | * Before we sweep, we should mark all free cells in a way that is |
Marko Mikulicic |
0:c0ecb8bf28eb | 20576 | * distinguishable from marked used cells. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20577 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20578 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20579 | struct gc_cell *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20580 | for (cur = a->free; cur != NULL; cur = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20581 | next = cur->head.link; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20582 | MARK_FREE(cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20583 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20584 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20586 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20587 | * We'll rebuild the whole `free` list, so initially we just reset it |
Marko Mikulicic |
0:c0ecb8bf28eb | 20588 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20589 | a->free = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20591 | for (b = a->blocks; b != NULL;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20592 | size_t freed_in_block = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20593 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20594 | * if it turns out that this block is 100% garbage |
Marko Mikulicic |
0:c0ecb8bf28eb | 20595 | * we can release the whole block, but the addition |
Marko Mikulicic |
0:c0ecb8bf28eb | 20596 | * of it's cells to the free list has to be undone. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20597 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20598 | struct gc_cell *prev_free = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20599 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20600 | for (cur = GC_CELL_OP(a, b->base, +, start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20601 | cur < GC_CELL_OP(a, b->base, +, b->size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20602 | cur = GC_CELL_OP(a, cur, +, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20603 | if (MARKED(cur)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20604 | /* The cell is used and marked */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20605 | UNMARK(cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20606 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20607 | a->alive++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20608 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20609 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20610 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20611 | * The cell is either: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20612 | * - free |
Marko Mikulicic |
0:c0ecb8bf28eb | 20613 | * - garbage that's about to be freed |
Marko Mikulicic |
0:c0ecb8bf28eb | 20614 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20616 | if (MARKED_FREE(cur)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20617 | /* The cell is free, so, just unmark it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20618 | UNMARK_FREE(cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20619 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20620 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20621 | * The cell is used and should be freed: call the destructor and |
Marko Mikulicic |
0:c0ecb8bf28eb | 20622 | * reset the memory |
Marko Mikulicic |
0:c0ecb8bf28eb | 20623 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20624 | if (a->destructor != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20625 | a->destructor(v7, cur); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20626 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20627 | memset(cur, 0, a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20628 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20629 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20630 | /* Add this cell to the `free` list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20631 | cur->head.link = a->free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20632 | a->free = cur; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20633 | freed_in_block++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20634 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20635 | a->garbage++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20636 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20637 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20638 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20640 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20641 | * don't free the initial block, which is at the tail |
Marko Mikulicic |
0:c0ecb8bf28eb | 20642 | * because it has a special size aimed at reducing waste |
Marko Mikulicic |
0:c0ecb8bf28eb | 20643 | * and simplifying initial startup. TODO(mkm): improve |
Marko Mikulicic |
0:c0ecb8bf28eb | 20644 | * */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20645 | if (b->next != NULL && freed_in_block == b->size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20646 | *prevp = b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20647 | gc_free_block(b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20648 | b = *prevp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20649 | a->free = prev_free; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20650 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20651 | prevp = &b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20652 | b = b->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20653 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20654 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20655 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20656 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20657 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20658 | * dense arrays contain only one property pointing to an mbuf with array values. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20659 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20660 | V7_PRIVATE void gc_mark_dense_array(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20661 | struct v7_generic_object *obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20662 | val_t v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20663 | struct mbuf *mbuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20664 | val_t *vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20666 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 20667 | /* TODO(mkm): use this when dense array promotion is implemented */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20668 | v = obj->properties->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20669 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 20670 | v = v7_get(v7, v7_object_to_value(&obj->base), "", 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20671 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20673 | mbuf = (struct mbuf *) v7_get_ptr(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20674 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20675 | /* function scope pointer is aliased to the object's prototype pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20676 | gc_mark(v7, v7_object_to_value(obj_prototype(v7, &obj->base))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20677 | MARK(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20679 | if (mbuf == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20680 | for (vp = (val_t *) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20681 | gc_mark(v7, *vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20682 | gc_mark_string(v7, vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20683 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20684 | UNMARK(obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20685 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20687 | V7_PRIVATE void gc_mark(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20688 | struct v7_object *obj_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20689 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20690 | struct v7_property *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20692 | if (!v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20693 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20694 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20695 | obj_base = get_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20697 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20698 | * we ignore objects that are not managed by V7 heap, such as frozen |
Marko Mikulicic |
0:c0ecb8bf28eb | 20699 | * objects, especially when on flash. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20700 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20701 | if (obj_base->attributes & V7_OBJ_OFF_HEAP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20702 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20703 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20704 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20705 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20706 | * we treat all object like things like objects but they might be functions, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20707 | * gc_gheck_val checks the appropriate arena per actual value type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20708 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20709 | if (!gc_check_val(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20710 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20711 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20712 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20713 | if (MARKED(obj_base)) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20714 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20715 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20716 | if (v7->freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20717 | freeze_obj(v7, v7->freeze_file, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20718 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20719 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20721 | if (obj_base->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20722 | struct v7_generic_object *obj = get_generic_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20723 | gc_mark_dense_array(v7, obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20724 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20725 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20726 | /* mark object itself, and its properties */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20727 | for ((prop = obj_base->properties), MARK(obj_base); prop != NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20728 | prop = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20729 | if (prop->attributes & _V7_PROPERTY_OFF_HEAP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20730 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20731 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20732 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20733 | if (!gc_check_ptr(&v7->property_arena, prop)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20734 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20735 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20736 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20737 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20738 | if (v7->freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20739 | freeze_prop(v7, v7->freeze_file, prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20740 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20741 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20743 | gc_mark_string(v7, &prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20744 | gc_mark_string(v7, &prop->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20745 | gc_mark(v7, prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20746 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20747 | next = prop->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20748 | MARK(prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20751 | /* mark object's prototype */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20752 | gc_mark(v7, v7_get_proto(v7, v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20754 | if (is_js_function(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20755 | struct v7_js_function *func = get_js_function_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20756 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20757 | /* mark function's scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20758 | gc_mark(v7, v7_object_to_value(&func->scope->base)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20760 | if (func->bcode != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20761 | gc_mark_vec_val(v7, &func->bcode->lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20762 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20763 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20764 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20765 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20766 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20768 | V7_PRIVATE size_t gc_arena_size(struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20769 | size_t size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20770 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20771 | for (b = a->blocks; b != NULL; b = b->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20772 | size += b->size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20773 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20774 | return size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20775 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20777 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20778 | * TODO(dfrank): move to core |
Marko Mikulicic |
0:c0ecb8bf28eb | 20779 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20780 | int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20781 | switch (what) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20782 | case V7_HEAP_STAT_HEAP_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20783 | return gc_arena_size(&v7->generic_object_arena) * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20784 | v7->generic_object_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20785 | gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20786 | gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20787 | case V7_HEAP_STAT_HEAP_USED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20788 | return v7->generic_object_arena.alive * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20789 | v7->generic_object_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20790 | v7->function_arena.alive * v7->function_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 20791 | v7->property_arena.alive * v7->property_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20792 | case V7_HEAP_STAT_STRING_HEAP_RESERVED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20793 | return v7->owned_strings.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20794 | case V7_HEAP_STAT_STRING_HEAP_USED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20795 | return v7->owned_strings.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20796 | case V7_HEAP_STAT_OBJ_HEAP_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20797 | return gc_arena_size(&v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20798 | case V7_HEAP_STAT_OBJ_HEAP_FREE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20799 | return gc_arena_size(&v7->generic_object_arena) - |
Marko Mikulicic |
0:c0ecb8bf28eb | 20800 | v7->generic_object_arena.alive; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20801 | case V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20802 | return v7->generic_object_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20803 | case V7_HEAP_STAT_FUNC_HEAP_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20804 | return gc_arena_size(&v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20805 | case V7_HEAP_STAT_FUNC_HEAP_FREE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20806 | return gc_arena_size(&v7->function_arena) - v7->function_arena.alive; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20807 | case V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20808 | return v7->function_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20809 | case V7_HEAP_STAT_PROP_HEAP_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20810 | return gc_arena_size(&v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20811 | case V7_HEAP_STAT_PROP_HEAP_FREE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20812 | return gc_arena_size(&v7->property_arena) - v7->property_arena.alive; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20813 | case V7_HEAP_STAT_PROP_HEAP_CELL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20814 | return v7->property_arena.cell_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20815 | case V7_HEAP_STAT_FUNC_AST_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20816 | return v7->function_arena_ast_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20817 | case V7_HEAP_STAT_BCODE_OPS_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20818 | return v7->bcode_ops_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20819 | case V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20820 | return v7->bcode_lit_total_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20821 | case V7_HEAP_STAT_BCODE_LIT_DESER_SIZE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20822 | return v7->bcode_lit_deser_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20823 | case V7_HEAP_STAT_FUNC_OWNED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20824 | return v7->owned_values.len / sizeof(val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20825 | case V7_HEAP_STAT_FUNC_OWNED_MAX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20826 | return v7->owned_values.size / sizeof(val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20829 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20830 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20831 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20832 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20833 | V7_PRIVATE void gc_dump_arena_stats(const char *msg, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20834 | (void) msg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20835 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20836 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 20837 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 20838 | if (a->verbose) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20839 | fprintf(stderr, "%s: total allocations %lu, max %lu, alive %lu\n", msg, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20840 | (long unsigned int) a->allocations, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20841 | (long unsigned int) gc_arena_size(a), (long unsigned int) a->alive); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20842 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20843 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20844 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20845 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20846 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20847 | V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20848 | return (((uint64_t)(uintptr_t) get_ptr(v)) & ~V7_TAG_MASK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 20849 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20850 | & 0xFFFFFFFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 20851 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20852 | ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20853 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20855 | V7_PRIVATE val_t gc_string_val_from_offset(uint64_t s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20856 | return s | V7_TAG_STRING_O; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20857 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20859 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20861 | static uint16_t next_asn(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20862 | if (v7->gc_next_asn == 0xFFFF) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20863 | /* Wrap around explicitly. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20864 | v7->gc_next_asn = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20865 | return 0xFFFF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20867 | return v7->gc_next_asn++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20868 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20869 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20870 | uint16_t gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20871 | uint16_t asn = next_asn(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20872 | (void) str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20873 | (void) len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20874 | #ifdef V7_GC_VERBOSE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20875 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20876 | * ESP SDK printf cannot cope with null strings |
Marko Mikulicic |
0:c0ecb8bf28eb | 20877 | * as created by s_concat. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20878 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20879 | if (str == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20880 | fprintf(stderr, "GC ASN %d: <nil>\n", asn); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20881 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20882 | fprintf(stderr, "GC ASN %d: \"%.*s\"\n", asn, (int) len, str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20883 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20884 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20885 | #ifdef V7_GC_PANIC_ON_ASN |
Marko Mikulicic |
0:c0ecb8bf28eb | 20886 | if (asn == (V7_GC_PANIC_ON_ASN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20887 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20889 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20890 | return asn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20893 | int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20894 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20895 | * This functions attempts to handle integer wraparound in a naive way and |
Marko Mikulicic |
0:c0ecb8bf28eb | 20896 | * will give false positives when more than 65536 strings are allocated |
Marko Mikulicic |
0:c0ecb8bf28eb | 20897 | * between GC runs. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20898 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20899 | int r = (n >= v7->gc_min_asn && n < v7->gc_next_asn) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 20900 | (v7->gc_min_asn > v7->gc_next_asn && |
Marko Mikulicic |
0:c0ecb8bf28eb | 20901 | (n >= v7->gc_min_asn || n < v7->gc_next_asn)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20902 | if (!r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20903 | fprintf(stderr, "GC ASN %d is not in [%d,%d)\n", n, v7->gc_min_asn, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20904 | v7->gc_next_asn); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20906 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20907 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20909 | void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20910 | if (!gc_is_valid_allocation_seqn(v7, n)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20911 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20912 | * TODO(dfrank) throw exception if V7_GC_ASN_PANIC is not defined. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20913 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20914 | #if 0 && !defined(V7_GC_ASN_PANIC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 20915 | throw_exception(v7, INTERNAL_ERROR, "Invalid ASN: %d", (int) n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20916 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 20917 | fprintf(stderr, "Invalid ASN: %d\n", (int) n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20918 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20919 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20921 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20923 | #endif /* V7_DISABLE_STR_ALLOC_SEQ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20925 | /* Mark a string value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20926 | void gc_mark_string(struct v7 *v7, val_t *v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20927 | val_t h, tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20928 | char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20930 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20931 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20932 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 20933 | * If a value points to an unmarked string we shall: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20934 | * 1. save the first 6 bytes of the string |
Marko Mikulicic |
0:c0ecb8bf28eb | 20935 | * since we need to be able to distinguish real values from |
Marko Mikulicic |
0:c0ecb8bf28eb | 20936 | * the saved first 6 bytes of the string, we need to tag the chunk |
Marko Mikulicic |
0:c0ecb8bf28eb | 20937 | * as V7_TAG_STRING_C |
Marko Mikulicic |
0:c0ecb8bf28eb | 20938 | * 2. encode value's address (v) into the first 6 bytes of the string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20939 | * 3. put the saved 8 bytes (tag + chunk) back into the value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20940 | * 4. mark the string by putting '\1' in the NUL terminator of the previous |
Marko Mikulicic |
0:c0ecb8bf28eb | 20941 | * string chunk. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20942 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20943 | * If a value points to an already marked string we shall: |
Marko Mikulicic |
0:c0ecb8bf28eb | 20944 | * (0, <6 bytes of a pointer to a val_t>), hence we have to skip |
Marko Mikulicic |
0:c0ecb8bf28eb | 20945 | * the first byte. We tag the value pointer as a V7_TAG_FOREIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 20946 | * so that it won't be followed during recursive mark. |
Marko Mikulicic |
0:c0ecb8bf28eb | 20947 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20948 | * ... the rest is the same |
Marko Mikulicic |
0:c0ecb8bf28eb | 20949 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 20950 | * Note: 64-bit pointers can be represented with 48-bits |
Marko Mikulicic |
0:c0ecb8bf28eb | 20951 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20953 | /* clang-format on */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20955 | if ((*v & V7_TAG_MASK) != V7_TAG_STRING_O) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20956 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20957 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20959 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20960 | if (v7->freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20961 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20963 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20964 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20965 | #ifdef V7_GC_VERBOSE |
Marko Mikulicic |
0:c0ecb8bf28eb | 20966 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20967 | uint16_t asn = (*v >> 32) & 0xFFFF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20968 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20969 | fprintf(stderr, "GC marking ASN %d: '%s'\n", asn, |
Marko Mikulicic |
0:c0ecb8bf28eb | 20970 | v7_get_string(v7, v, &size)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20971 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20972 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20974 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 20975 | gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20976 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 20977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20978 | s = v7->owned_strings.buf + gc_string_val_to_offset(*v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20979 | assert(s < v7->owned_strings.buf + v7->owned_strings.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20980 | if (s[-1] == '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20981 | memcpy(&tmp, s, sizeof(tmp) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20982 | tmp |= V7_TAG_STRING_C; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20983 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20984 | memcpy(&tmp, s, sizeof(tmp) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20985 | tmp |= V7_TAG_FOREIGN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20986 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20988 | h = (val_t)(uintptr_t) v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20989 | s[-1] = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20990 | memcpy(s, &h, sizeof(h) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20991 | memcpy(v, &tmp, sizeof(tmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 20992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 20993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20994 | void gc_compact_strings(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 20995 | char *p = v7->owned_strings.buf + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20996 | uint64_t h, next, head = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20997 | int len, llen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 20998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 20999 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21000 | v7->gc_min_asn = v7->gc_next_asn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21001 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21002 | while (p < v7->owned_strings.buf + v7->owned_strings.len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21003 | if (p[-1] == '\1') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21004 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21005 | /* Not using gc_next_allocation_seqn() as we don't have full string. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21006 | uint16_t asn = next_asn(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21007 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21008 | /* relocate and update ptrs */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21009 | h = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21010 | memcpy(&h, p, sizeof(h) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21012 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21013 | * relocate pointers until we find the tail. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21014 | * The tail is marked with V7_TAG_STRING_C, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21015 | * while val_t link pointers are tagged with V7_TAG_FOREIGN |
Marko Mikulicic |
0:c0ecb8bf28eb | 21016 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21017 | for (; (h & V7_TAG_MASK) != V7_TAG_STRING_C; h = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21018 | h &= ~V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21019 | memcpy(&next, (char *) (uintptr_t) h, sizeof(h)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21021 | *(val_t *) (uintptr_t) h = gc_string_val_from_offset(head) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21022 | #ifndef V7_DISABLE_STR_ALLOC_SEQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21023 | | ((val_t) asn << 32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21024 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21025 | ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21027 | h &= ~V7_TAG_MASK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21029 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21030 | * the tail contains the first 6 bytes we stole from |
Marko Mikulicic |
0:c0ecb8bf28eb | 21031 | * the actual string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21032 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21033 | len = decode_varint((unsigned char *) &h, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21034 | len += llen + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21035 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21036 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21037 | * restore the saved 6 bytes |
Marko Mikulicic |
0:c0ecb8bf28eb | 21038 | * TODO(mkm): think about endianness |
Marko Mikulicic |
0:c0ecb8bf28eb | 21039 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21040 | memcpy(p, &h, sizeof(h) - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21042 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21043 | * and relocate the string data by packing it to the left. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21044 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21045 | memmove(v7->owned_strings.buf + head, p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21046 | v7->owned_strings.buf[head - 1] = 0x0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21047 | #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21048 | fprintf(stderr, "GC updated ASN %d: \"%.*s\"\n", asn, len - llen - 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21049 | v7->owned_strings.buf + head + llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21050 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21051 | p += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21052 | head += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21053 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21054 | len = decode_varint((unsigned char *) p, &llen); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21055 | len += llen + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21056 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21057 | p += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21059 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21061 | #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21062 | fprintf(stderr, "GC valid ASN range: [%d,%d)\n", v7->gc_min_asn, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21063 | v7->gc_next_asn); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21064 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21066 | v7->owned_strings.len = head; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21069 | void gc_dump_owned_strings(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21070 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21071 | for (i = 0; i < v7->owned_strings.len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21072 | if (isprint((unsigned char) v7->owned_strings.buf[i])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21073 | fputc(v7->owned_strings.buf[i], stderr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21074 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21075 | fputc('.', stderr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21076 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21078 | fputc('\n', stderr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21079 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21080 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21081 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21082 | * builting on gcc, tried out by redefining it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21083 | * Using null pointer as base can trigger undefined behavior, hence |
Marko Mikulicic |
0:c0ecb8bf28eb | 21084 | * a portable workaround that involves a valid yet dummy pointer. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21085 | * It's meant to be used as a contant expression. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21086 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21087 | #ifndef offsetof |
Marko Mikulicic |
0:c0ecb8bf28eb | 21088 | #define offsetof(st, m) (((ptrdiff_t)(&((st *) 32)->m)) - 32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21089 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21091 | V7_PRIVATE void compute_need_gc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21092 | struct mbuf *m = &v7->owned_strings; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21093 | if ((double) m->len / (double) m->size > 0.9) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21094 | v7->need_gc = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21095 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21096 | /* TODO(mkm): check free heap */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21097 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21098 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21099 | V7_PRIVATE int maybe_gc(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21100 | if (!v7->inhibit_gc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21101 | v7_gc(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21102 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21103 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21104 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21105 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21106 | #if defined(V7_GC_VERBOSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21107 | static int gc_pass = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21108 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21110 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21111 | * mark an array of `val_t` values (*not pointers* to them) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21112 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21113 | static void gc_mark_val_array(struct v7 *v7, val_t *vals, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21114 | val_t *vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21115 | for (vp = vals; vp < vals + len; vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21116 | gc_mark(v7, *vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21117 | gc_mark_string(v7, vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21118 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21121 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21122 | * mark an mbuf containing *pointers* to `val_t` values |
Marko Mikulicic |
0:c0ecb8bf28eb | 21123 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21124 | static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21125 | val_t **vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21126 | for (vp = (val_t **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21127 | gc_mark(v7, **vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21128 | gc_mark_string(v7, *vp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21129 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21130 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21132 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21133 | * mark an mbuf containing `val_t` values (*not pointers* to them) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21134 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21135 | static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21136 | gc_mark_val_array(v7, (val_t *) mbuf->buf, mbuf->len / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21137 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21138 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21139 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21140 | * mark a vector containing `val_t` values (*not pointers* to them) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21141 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21142 | static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21143 | gc_mark_val_array(v7, (val_t *) vec->p, vec->len / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21144 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21146 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21147 | * mark an mbuf containing foreign pointers to `struct bcode` |
Marko Mikulicic |
0:c0ecb8bf28eb | 21148 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21149 | static void gc_mark_mbuf_bcode_pt(struct v7 *v7, const struct mbuf *mbuf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21150 | struct bcode **vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21151 | for (vp = (struct bcode **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21152 | vp++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21153 | gc_mark_vec_val(v7, &(*vp)->lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21154 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21155 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21157 | static void gc_mark_call_stack_private( |
Marko Mikulicic |
0:c0ecb8bf28eb | 21158 | struct v7 *v7, struct v7_call_frame_private *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21159 | gc_mark_val_array(v7, (val_t *) &call_stack->vals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21160 | sizeof(call_stack->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21161 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21162 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21163 | static void gc_mark_call_stack_cfunc(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21164 | struct v7_call_frame_cfunc *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21165 | gc_mark_val_array(v7, (val_t *) &call_stack->vals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21166 | sizeof(call_stack->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21167 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21169 | static void gc_mark_call_stack_bcode(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21170 | struct v7_call_frame_bcode *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21171 | gc_mark_val_array(v7, (val_t *) &call_stack->vals, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21172 | sizeof(call_stack->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21175 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21176 | * mark `struct v7_call_frame` and all its back-linked frames |
Marko Mikulicic |
0:c0ecb8bf28eb | 21177 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21178 | static void gc_mark_call_stack(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21179 | struct v7_call_frame_base *call_stack) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21180 | while (call_stack != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21181 | if (call_stack->type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21182 | gc_mark_call_stack_bcode(v7, (struct v7_call_frame_bcode *) call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21183 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21185 | if (call_stack->type_mask & V7_CALL_FRAME_MASK_PRIVATE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21186 | gc_mark_call_stack_private(v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21187 | (struct v7_call_frame_private *) call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21188 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21189 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21190 | if (call_stack->type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21191 | gc_mark_call_stack_cfunc(v7, (struct v7_call_frame_cfunc *) call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21194 | call_stack = call_stack->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21196 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21198 | /* Perform garbage collection */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21199 | void v7_gc(struct v7 *v7, int full) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21200 | #ifdef V7_DISABLE_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 21201 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21202 | (void) full; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21203 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21204 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21205 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21206 | #if defined(V7_GC_VERBOSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21207 | fprintf(stderr, "V7 GC pass %d\n", ++gc_pass); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21208 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21210 | gc_dump_arena_stats("Before GC objects", &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21211 | gc_dump_arena_stats("Before GC functions", &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21212 | gc_dump_arena_stats("Before GC properties", &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21214 | gc_mark_call_stack(v7, v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21216 | gc_mark_val_array(v7, (val_t *) &v7->vals, sizeof(v7->vals) / sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21217 | /* mark all items on bcode stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21218 | gc_mark_mbuf_val(v7, &v7->stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21220 | /* mark literals and names of all the active bcodes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21221 | gc_mark_mbuf_bcode_pt(v7, &v7->act_bcodes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21223 | gc_mark_mbuf_pt(v7, &v7->tmp_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21224 | gc_mark_mbuf_pt(v7, &v7->owned_values); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21226 | gc_compact_strings(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21228 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 21229 | gc_sweep_malloc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21230 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21231 | gc_sweep(v7, &v7->generic_object_arena, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21232 | gc_sweep(v7, &v7->function_arena, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21233 | gc_sweep(v7, &v7->property_arena, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21234 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21236 | gc_dump_arena_stats("After GC objects", &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21237 | gc_dump_arena_stats("After GC functions", &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21238 | gc_dump_arena_stats("After GC properties", &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21239 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21240 | if (full) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21241 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21242 | * In case of full GC, we also resize strings buffer, but we still leave |
Marko Mikulicic |
0:c0ecb8bf28eb | 21243 | * some extra space (at most, `_V7_STRING_BUF_RESERVE`) in order to avoid |
Marko Mikulicic |
0:c0ecb8bf28eb | 21244 | * frequent reallocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 21245 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21246 | size_t trimmed_size = v7->owned_strings.len + _V7_STRING_BUF_RESERVE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21247 | if (trimmed_size < v7->owned_strings.size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21248 | heapusage_dont_count(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21249 | mbuf_resize(&v7->owned_strings, trimmed_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21250 | heapusage_dont_count(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21251 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21252 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21253 | #endif /* V7_DISABLE_GC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21254 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21256 | V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21257 | if (is_js_function(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21258 | return gc_check_ptr(&v7->function_arena, get_js_function_struct(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21259 | } else if (v7_is_object(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21260 | return gc_check_ptr(&v7->generic_object_arena, get_object_struct(v)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21261 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21262 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21263 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21264 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21265 | V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21266 | #ifdef V7_MALLOC_GC |
Marko Mikulicic |
0:c0ecb8bf28eb | 21267 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21268 | (void) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21269 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21270 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21271 | const struct gc_cell *p = (const struct gc_cell *) ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21272 | struct gc_block *b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21273 | for (b = a->blocks; b != NULL; b = b->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21274 | if (p >= b->base && p < GC_CELL_OP(a, b->base, +, b->size)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21275 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21276 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21277 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21278 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21279 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21280 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21281 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 21282 | #line 1 "v7/src/freeze.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21283 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21284 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21285 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 21286 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 21287 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21289 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21290 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21291 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21292 | /* Amalgamated: #include "v7/src/freeze.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21293 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21294 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21295 | /* Amalgamated: #include "common/base64.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21296 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21298 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 21299 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21300 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 21301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21302 | V7_PRIVATE void freeze(struct v7 *v7, char *filename) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21303 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21305 | v7->freeze_file = fopen(filename, "w"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21306 | assert(v7->freeze_file != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21308 | #ifndef V7_FREEZE_NOT_READONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 21309 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21310 | * We have to remove `global` from the global object since |
Marko Mikulicic |
0:c0ecb8bf28eb | 21311 | * when thawing global will actually be a new mutable object |
Marko Mikulicic |
0:c0ecb8bf28eb | 21312 | * living on the heap. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21313 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21314 | v7_del(v7, v7->vals.global_object, "global", 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21315 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21317 | for (i = 0; i < sizeof(v7->vals) / sizeof(val_t); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21318 | val_t v = ((val_t *) &v7->vals)[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21319 | fprintf(v7->freeze_file, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21320 | "{\"type\":\"global\", \"idx\":%zu, \"value\":\"%p\"}\n", i, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21321 | (void *) (v7_is_object(v) ? get_object_struct(v) : 0x0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21324 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21325 | * since v7->freeze_file is not NULL this will cause freeze_obj and |
Marko Mikulicic |
0:c0ecb8bf28eb | 21326 | * freeze_prop to be called for each reachable object and property. |
Marko Mikulicic |
0:c0ecb8bf28eb | 21327 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21328 | v7_gc(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21329 | assert(v7->stack.len == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21330 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21331 | fclose(v7->freeze_file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21332 | v7->freeze_file = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21333 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21334 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21335 | static char *freeze_vec(struct v7_vec *vec) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21336 | char *res = (char *) malloc(512 + vec->len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21337 | res[0] = '"'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21338 | cs_base64_encode((const unsigned char *) vec->p, vec->len, &res[1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21339 | strcat(res, "\""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21340 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21343 | V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21344 | struct v7_object *obj_base = get_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21345 | unsigned int attrs = V7_OBJ_OFF_HEAP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21347 | #ifndef V7_FREEZE_NOT_READONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 21348 | attrs |= V7_OBJ_NOT_EXTENSIBLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21349 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21351 | if (is_js_function(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21352 | struct v7_js_function *func = get_js_function_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21353 | struct bcode *bcode = func->bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21354 | char *jops = freeze_vec(&bcode->ops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21355 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21357 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21358 | "{\"type\":\"func\", \"addr\":\"%p\", \"props\":\"%p\", " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21359 | "\"attrs\":%d, \"scope\":\"%p\", \"bcode\":\"%p\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21360 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21361 | ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21362 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21363 | "}\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21364 | (void *) obj_base, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21365 | (void *) ((uintptr_t) obj_base->properties & ~0x1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 21366 | obj_base->attributes | attrs, (void *) func->scope, (void *) bcode |
Marko Mikulicic |
0:c0ecb8bf28eb | 21367 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21368 | , |
Marko Mikulicic |
0:c0ecb8bf28eb | 21369 | obj_base->entity_id_base, obj_base->entity_id_spec |
Marko Mikulicic |
0:c0ecb8bf28eb | 21370 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21371 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21372 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21373 | "{\"type\":\"bcode\", \"addr\":\"%p\", \"args_cnt\":%d, " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21374 | "\"names_cnt\":%d, " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21375 | "\"strict_mode\": %d, \"func_name_present\": %d, \"ops\":%s, " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21376 | "\"lit\": [", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21377 | (void *) bcode, bcode->args_cnt, bcode->names_cnt, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21378 | bcode->strict_mode, bcode->func_name_present, jops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21380 | for (i = 0; (size_t) i < bcode->lit.len / sizeof(val_t); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21381 | val_t v = ((val_t *) bcode->lit.p)[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21382 | const char *str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21383 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21384 | if (((v & V7_TAG_MASK) == V7_TAG_STRING_O || |
Marko Mikulicic |
0:c0ecb8bf28eb | 21385 | (v & V7_TAG_MASK) == V7_TAG_STRING_F) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 21386 | (str = v7_get_cstring(v7, &v)) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21387 | fprintf(f, "{\"str\": \"%s\"}", str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21388 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21389 | fprintf(f, "{\"val\": \"0x%" INT64_X_FMT "\"}", v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21390 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21391 | if ((size_t) i != bcode->lit.len / sizeof(val_t) - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21392 | fprintf(f, ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21393 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21394 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21396 | fprintf(f, "]}\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21397 | free(jops); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21398 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21399 | struct v7_generic_object *gob = get_generic_object_struct(v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21400 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21401 | "{\"type\":\"obj\", \"addr\":\"%p\", \"props\":\"%p\", " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21402 | "\"attrs\":%d, \"proto\":\"%p\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21403 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21404 | ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" " |
Marko Mikulicic |
0:c0ecb8bf28eb | 21405 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21406 | "}\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21407 | (void *) obj_base, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21408 | (void *) ((uintptr_t) obj_base->properties & ~0x1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 21409 | obj_base->attributes | attrs, (void *) gob->prototype |
Marko Mikulicic |
0:c0ecb8bf28eb | 21410 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21411 | , |
Marko Mikulicic |
0:c0ecb8bf28eb | 21412 | obj_base->entity_id_base, obj_base->entity_id_spec |
Marko Mikulicic |
0:c0ecb8bf28eb | 21413 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21414 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21415 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21417 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21418 | V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21419 | unsigned int attrs = _V7_PROPERTY_OFF_HEAP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21420 | #ifndef V7_FREEZE_NOT_READONLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 21421 | attrs |= V7_PROPERTY_NON_WRITABLE | V7_PROPERTY_NON_CONFIGURABLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21422 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21424 | fprintf(f, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21425 | "{\"type\":\"prop\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21426 | " \"addr\":\"%p\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21427 | " \"next\":\"%p\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21428 | " \"attrs\":%d," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21429 | " \"name\":\"0x%" INT64_X_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 21430 | "\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21431 | " \"value_type\":%d," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21432 | " \"value\":\"0x%" INT64_X_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 21433 | "\"," |
Marko Mikulicic |
0:c0ecb8bf28eb | 21434 | " \"name_str\":\"%s\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21435 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21436 | ", \"entity_id\":\"%d\"" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21437 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21438 | "}\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 21439 | (void *) prop, (void *) prop->next, prop->attributes | attrs, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21440 | prop->name, val_type(v7, prop->value), prop->value, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21441 | v7_get_cstring(v7, &prop->name) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21442 | #if defined(V7_ENABLE_ENTITY_IDS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21443 | , |
Marko Mikulicic |
0:c0ecb8bf28eb | 21444 | prop->entity_id |
Marko Mikulicic |
0:c0ecb8bf28eb | 21445 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21446 | ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 21447 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 21448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21449 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21450 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 21451 | #line 1 "v7/src/parser.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 21452 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21453 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21454 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 21455 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 21456 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21457 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21458 | /* Amalgamated: #include "common/coroutine.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21459 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21460 | /* Amalgamated: #include "v7/src/parser.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21461 | /* Amalgamated: #include "v7/src/tokenizer.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21462 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21463 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21464 | /* Amalgamated: #include "v7/src/ast.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21465 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21466 | /* Amalgamated: #include "v7/src/cyg_profile.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21467 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21468 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21470 | #define ACCEPT(t) (((v7)->cur_tok == (t)) ? next_tok((v7)), 1 : 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21471 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21472 | #define EXPECT(t) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21473 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21474 | if ((v7)->cur_tok != (t)) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21475 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21476 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21477 | next_tok(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21478 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21479 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21480 | #define PARSE_WITH_OPT_ARG(tag, arg_tag, arg_parser, label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21481 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21482 | if (end_of_statement(v7) == V7_OK) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21483 | add_node(v7, a, (tag)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21484 | } else { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21485 | add_node(v7, a, (arg_tag)); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21486 | arg_parser(label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21487 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21488 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21490 | #define N (CR_ARG_RET_PT()->arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21492 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21493 | * User functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 21494 | * (as well as other in-function entry points) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21495 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21496 | enum my_fid { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21497 | fid_none = CR_FID__NONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21499 | /* parse_script function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21500 | fid_parse_script = CR_FID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21501 | fid_p_script_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21502 | fid_p_script_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21503 | fid_p_script_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21504 | fid_p_script_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21505 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21506 | /* parse_use_strict function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21507 | fid_parse_use_strict, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21508 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21509 | /* parse_body function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21510 | fid_parse_body, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21511 | fid_p_body_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21512 | fid_p_body_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21513 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21514 | /* parse_statement function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21515 | fid_parse_statement, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21516 | fid_p_stat_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21517 | fid_p_stat_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21518 | fid_p_stat_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21519 | fid_p_stat_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21520 | fid_p_stat_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21521 | fid_p_stat_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21522 | fid_p_stat_7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21523 | fid_p_stat_8, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21524 | fid_p_stat_9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21525 | fid_p_stat_10, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21526 | fid_p_stat_11, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21527 | fid_p_stat_12, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21528 | fid_p_stat_13, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21529 | fid_p_stat_14, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21531 | /* parse_expression function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21532 | fid_parse_expression, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21533 | fid_p_expr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21534 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21535 | /* parse_assign function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21536 | fid_parse_assign, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21537 | fid_p_assign_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21538 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21539 | /* parse_binary function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21540 | fid_parse_binary, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21541 | fid_p_binary_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21542 | fid_p_binary_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21543 | fid_p_binary_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21544 | fid_p_binary_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21545 | fid_p_binary_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21546 | fid_p_binary_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21548 | /* parse_prefix function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21549 | fid_parse_prefix, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21550 | fid_p_prefix_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21552 | /* parse_postfix function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21553 | fid_parse_postfix, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21554 | fid_p_postfix_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21556 | /* parse_callexpr function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21557 | fid_parse_callexpr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21558 | fid_p_callexpr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21559 | fid_p_callexpr_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21560 | fid_p_callexpr_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21562 | /* parse_newexpr function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21563 | fid_parse_newexpr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21564 | fid_p_newexpr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21565 | fid_p_newexpr_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21566 | fid_p_newexpr_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21567 | fid_p_newexpr_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21568 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21569 | /* parse_terminal function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21570 | fid_parse_terminal, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21571 | fid_p_terminal_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21572 | fid_p_terminal_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21573 | fid_p_terminal_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21574 | fid_p_terminal_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21576 | /* parse_block function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21577 | fid_parse_block, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21578 | fid_p_block_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21580 | /* parse_if function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21581 | fid_parse_if, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21582 | fid_p_if_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21583 | fid_p_if_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21584 | fid_p_if_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21586 | /* parse_while function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21587 | fid_parse_while, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21588 | fid_p_while_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21589 | fid_p_while_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21591 | /* parse_ident function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21592 | fid_parse_ident, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21593 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21594 | /* parse_ident_allow_reserved_words function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21595 | fid_parse_ident_allow_reserved_words, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21596 | fid_p_ident_arw_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21597 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21598 | /* parse_funcdecl function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21599 | fid_parse_funcdecl, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21600 | fid_p_funcdecl_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21601 | fid_p_funcdecl_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21602 | fid_p_funcdecl_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21603 | fid_p_funcdecl_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21604 | fid_p_funcdecl_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21605 | fid_p_funcdecl_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21606 | fid_p_funcdecl_7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21607 | fid_p_funcdecl_8, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21608 | fid_p_funcdecl_9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21610 | /* parse_arglist function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21611 | fid_parse_arglist, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21612 | fid_p_arglist_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21614 | /* parse_member function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21615 | fid_parse_member, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21616 | fid_p_member_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21618 | /* parse_memberexpr function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21619 | fid_parse_memberexpr, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21620 | fid_p_memberexpr_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21621 | fid_p_memberexpr_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21622 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21623 | /* parse_var function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21624 | fid_parse_var, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21625 | fid_p_var_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21627 | /* parse_prop function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21628 | fid_parse_prop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21629 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 21630 | fid_p_prop_1_getter, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21631 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21632 | fid_p_prop_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21633 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 21634 | fid_p_prop_3_setter, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21635 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21636 | fid_p_prop_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21638 | /* parse_dowhile function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21639 | fid_parse_dowhile, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21640 | fid_p_dowhile_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21641 | fid_p_dowhile_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21643 | /* parse_for function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21644 | fid_parse_for, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21645 | fid_p_for_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21646 | fid_p_for_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21647 | fid_p_for_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21648 | fid_p_for_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21649 | fid_p_for_5, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21650 | fid_p_for_6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21652 | /* parse_try function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21653 | fid_parse_try, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21654 | fid_p_try_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21655 | fid_p_try_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21656 | fid_p_try_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21657 | fid_p_try_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21658 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21659 | /* parse_switch function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21660 | fid_parse_switch, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21661 | fid_p_switch_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21662 | fid_p_switch_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21663 | fid_p_switch_3, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21664 | fid_p_switch_4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21666 | /* parse_with function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21667 | fid_parse_with, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21668 | fid_p_with_1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21669 | fid_p_with_2, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21671 | MY_FID_CNT |
Marko Mikulicic |
0:c0ecb8bf28eb | 21672 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21674 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 21675 | * User exception IDs. The first one should have value `CR_EXC_ID__USER` |
Marko Mikulicic |
0:c0ecb8bf28eb | 21676 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21677 | enum parser_exc_id { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21678 | PARSER_EXC_ID__NONE = CR_EXC_ID__NONE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21679 | PARSER_EXC_ID__SYNTAX_ERROR = CR_EXC_ID__USER, |
Marko Mikulicic |
0:c0ecb8bf28eb | 21680 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21681 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21682 | /* structures with locals and args {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21683 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21684 | /* parse_script {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21686 | /* parse_script's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21687 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21688 | typedef struct fid_parse_script_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21689 | } fid_parse_script_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21690 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21691 | typedef cr_zero_size_type_t fid_parse_script_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21692 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21694 | /* parse_script's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21695 | typedef struct fid_parse_script_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21696 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21697 | struct fid_parse_script_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21698 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21699 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21700 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21701 | ast_off_t outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21702 | int saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21703 | } fid_parse_script_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21704 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21705 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21707 | /* parse_use_strict {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21708 | /* parse_use_strict's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21709 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21710 | typedef struct fid_parse_use_strict_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21711 | } fid_parse_use_strict_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21712 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21713 | typedef cr_zero_size_type_t fid_parse_use_strict_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21714 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21715 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21716 | /* parse_use_strict's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21717 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21718 | typedef struct fid_parse_use_strict_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21719 | struct fid_parse_use_strict_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21720 | } fid_parse_use_strict_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21721 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21722 | typedef cr_zero_size_type_t fid_parse_use_strict_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21723 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21725 | #define CALL_PARSE_USE_STRICT(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21726 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21727 | CR_CALL(fid_parse_use_strict, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21728 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21730 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21731 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21732 | /* parse_body {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21733 | /* parse_body's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21734 | typedef struct fid_parse_body_arg { enum v7_tok end; } fid_parse_body_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21736 | /* parse_body's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21737 | typedef struct fid_parse_body_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21738 | struct fid_parse_body_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21739 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21740 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21741 | } fid_parse_body_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21742 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21743 | #define CALL_PARSE_BODY(_end, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21744 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21745 | N.fid_parse_body.end = (_end); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21746 | CR_CALL(fid_parse_body, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21747 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21748 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21749 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21750 | /* parse_statement {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21751 | /* parse_statement's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21752 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21753 | typedef struct fid_parse_statement_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21754 | } fid_parse_statement_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21755 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21756 | typedef cr_zero_size_type_t fid_parse_statement_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21757 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21758 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21759 | /* parse_statement's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21760 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21761 | typedef struct fid_parse_statement_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21762 | struct fid_parse_statement_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21763 | } fid_parse_statement_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21764 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21765 | typedef cr_zero_size_type_t fid_parse_statement_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21766 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21768 | #define CALL_PARSE_STATEMENT(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21769 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21770 | CR_CALL(fid_parse_statement, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21771 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21772 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21773 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21774 | /* parse_expression {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21775 | /* parse_expression's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21776 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21777 | typedef struct fid_parse_expression_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21778 | } fid_parse_expression_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21779 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21780 | typedef cr_zero_size_type_t fid_parse_expression_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21781 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21783 | /* parse_expression's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21784 | typedef struct fid_parse_expression_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21785 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21786 | struct fid_parse_expression_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21787 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21789 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21790 | int group; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21791 | } fid_parse_expression_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21792 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21793 | #define CALL_PARSE_EXPRESSION(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21794 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21795 | CR_CALL(fid_parse_expression, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21796 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21797 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21799 | /* parse_assign {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21800 | /* parse_assign's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21801 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21802 | typedef struct fid_parse_assign_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21803 | } fid_parse_assign_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21804 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21805 | typedef cr_zero_size_type_t fid_parse_assign_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21806 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21808 | /* parse_assign's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21809 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21810 | typedef struct fid_parse_assign_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21811 | struct fid_parse_assign_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21812 | } fid_parse_assign_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21813 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21814 | typedef cr_zero_size_type_t fid_parse_assign_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21815 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21817 | #define CALL_PARSE_ASSIGN(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21818 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21819 | CR_CALL(fid_parse_assign, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21820 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21821 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21823 | /* parse_binary {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21824 | /* parse_binary's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21825 | typedef struct fid_parse_binary_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21826 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21827 | uint8_t min_level; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21828 | } fid_parse_binary_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21830 | /* parse_binary's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21831 | typedef struct fid_parse_binary_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21832 | struct fid_parse_binary_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21834 | uint8_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21835 | /* during iteration, it becomes negative, so should be signed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21836 | int8_t level; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21837 | uint8_t /*enum v7_tok*/ tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21838 | uint8_t /*enum ast_tag*/ ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21839 | ast_off_t saved_mbuf_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21840 | } fid_parse_binary_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21842 | #define CALL_PARSE_BINARY(_level, _pos, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21843 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21844 | N.fid_parse_binary.min_level = (_level); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21845 | N.fid_parse_binary.pos = (_pos); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21846 | CR_CALL(fid_parse_binary, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21847 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21848 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21850 | /* parse_prefix {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21851 | /* parse_prefix's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21852 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21853 | typedef struct fid_parse_prefix_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21854 | } fid_parse_prefix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21855 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21856 | typedef cr_zero_size_type_t fid_parse_prefix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21857 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21859 | /* parse_prefix's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21860 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21861 | typedef struct fid_parse_prefix_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21862 | struct fid_parse_prefix_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21863 | } fid_parse_prefix_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21864 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21865 | typedef cr_zero_size_type_t fid_parse_prefix_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21866 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21867 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21868 | #define CALL_PARSE_PREFIX(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21869 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21870 | CR_CALL(fid_parse_prefix, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21871 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21872 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21874 | /* parse_postfix {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21875 | /* parse_postfix's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21876 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21877 | typedef struct fid_parse_postfix_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21878 | } fid_parse_postfix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21879 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21880 | typedef cr_zero_size_type_t fid_parse_postfix_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21881 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21882 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21883 | /* parse_postfix's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21884 | typedef struct fid_parse_postfix_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21885 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21886 | struct fid_parse_postfix_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21887 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21889 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21890 | } fid_parse_postfix_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21892 | #define CALL_PARSE_POSTFIX(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21893 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21894 | CR_CALL(fid_parse_postfix, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21895 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21896 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21897 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21898 | /* parse_callexpr {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21899 | /* parse_callexpr's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21900 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21901 | typedef struct fid_parse_callexpr_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21902 | } fid_parse_callexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21903 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21904 | typedef cr_zero_size_type_t fid_parse_callexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21905 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21907 | /* parse_callexpr's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21908 | typedef struct fid_parse_callexpr_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21909 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21910 | struct fid_parse_callexpr_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21911 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21913 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21914 | } fid_parse_callexpr_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21916 | #define CALL_PARSE_CALLEXPR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21917 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21918 | CR_CALL(fid_parse_callexpr, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21919 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21920 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21922 | /* parse_newexpr {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21923 | /* parse_newexpr's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21924 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21925 | typedef struct fid_parse_newexpr_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21926 | } fid_parse_newexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21927 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21928 | typedef cr_zero_size_type_t fid_parse_newexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21929 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21931 | /* parse_newexpr's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21932 | typedef struct fid_parse_newexpr_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21933 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21934 | struct fid_parse_newexpr_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21935 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21937 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21938 | } fid_parse_newexpr_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21940 | #define CALL_PARSE_NEWEXPR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21941 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21942 | CR_CALL(fid_parse_newexpr, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21943 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21944 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21946 | /* parse_terminal {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21947 | /* parse_terminal's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21948 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21949 | typedef struct fid_parse_terminal_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21950 | } fid_parse_terminal_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21951 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21952 | typedef cr_zero_size_type_t fid_parse_terminal_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21953 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21955 | /* parse_terminal's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21956 | typedef struct fid_parse_terminal_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21957 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21958 | struct fid_parse_terminal_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21959 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21961 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21962 | } fid_parse_terminal_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21964 | #define CALL_PARSE_TERMINAL(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21965 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21966 | CR_CALL(fid_parse_terminal, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21967 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21968 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21970 | /* parse_block {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21971 | /* parse_block's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21972 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21973 | typedef struct fid_parse_block_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21974 | } fid_parse_block_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21975 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21976 | typedef cr_zero_size_type_t fid_parse_block_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21977 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21979 | /* parse_block's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21980 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21981 | typedef struct fid_parse_block_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21982 | struct fid_parse_block_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21983 | } fid_parse_block_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21984 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 21985 | typedef cr_zero_size_type_t fid_parse_block_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21986 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 21987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21988 | #define CALL_PARSE_BLOCK(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21989 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21990 | CR_CALL(fid_parse_block, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21991 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 21992 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 21994 | /* parse_if {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21995 | /* parse_if's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 21996 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 21997 | typedef struct fid_parse_if_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 21998 | } fid_parse_if_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 21999 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22000 | typedef cr_zero_size_type_t fid_parse_if_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22001 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22003 | /* parse_if's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22004 | typedef struct fid_parse_if_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22005 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22006 | struct fid_parse_if_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22007 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22009 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22010 | } fid_parse_if_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22012 | #define CALL_PARSE_IF(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22013 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22014 | CR_CALL(fid_parse_if, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22015 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22016 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22018 | /* parse_while {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22019 | /* parse_while's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22020 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22021 | typedef struct fid_parse_while_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22022 | } fid_parse_while_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22023 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22024 | typedef cr_zero_size_type_t fid_parse_while_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22025 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22026 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22027 | /* parse_while's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22028 | typedef struct fid_parse_while_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22029 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22030 | struct fid_parse_while_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22031 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22033 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22034 | uint8_t saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22035 | } fid_parse_while_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22037 | #define CALL_PARSE_WHILE(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22038 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22039 | CR_CALL(fid_parse_while, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22040 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22041 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22042 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22043 | /* parse_ident {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22044 | /* parse_ident's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22045 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22046 | typedef struct fid_parse_ident_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22047 | } fid_parse_ident_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22048 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22049 | typedef cr_zero_size_type_t fid_parse_ident_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22050 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22051 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22052 | /* parse_ident's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22053 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22054 | typedef struct fid_parse_ident_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22055 | struct fid_parse_ident_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22056 | } fid_parse_ident_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22057 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22058 | typedef cr_zero_size_type_t fid_parse_ident_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22059 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22061 | #define CALL_PARSE_IDENT(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22062 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22063 | CR_CALL(fid_parse_ident, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22064 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22065 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22066 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22067 | /* parse_ident_allow_reserved_words {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22068 | /* parse_ident_allow_reserved_words's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22069 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22070 | typedef struct fid_parse_ident_allow_reserved_words_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22071 | } fid_parse_ident_allow_reserved_words_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22072 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22073 | typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22074 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22076 | /* parse_ident_allow_reserved_words's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22077 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22078 | typedef struct fid_parse_ident_allow_reserved_words_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22079 | struct fid_parse_ident_allow_reserved_words_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22080 | } fid_parse_ident_allow_reserved_words_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22081 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22082 | typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22083 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22084 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22085 | #define CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22086 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22087 | CR_CALL(fid_parse_ident_allow_reserved_words, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22088 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22089 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22091 | /* parse_funcdecl {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22092 | /* parse_funcdecl's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22093 | typedef struct fid_parse_funcdecl_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22094 | uint8_t require_named; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22095 | uint8_t reserved_name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22096 | } fid_parse_funcdecl_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22098 | /* parse_funcdecl's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22099 | typedef struct fid_parse_funcdecl_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22100 | struct fid_parse_funcdecl_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22102 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22103 | ast_off_t outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22104 | uint8_t saved_in_function; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22105 | uint8_t saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22106 | } fid_parse_funcdecl_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22107 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22108 | #define CALL_PARSE_FUNCDECL(_require_named, _reserved_name, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22109 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22110 | N.fid_parse_funcdecl.require_named = (_require_named); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22111 | N.fid_parse_funcdecl.reserved_name = (_reserved_name); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22112 | CR_CALL(fid_parse_funcdecl, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22113 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22114 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22115 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22116 | /* parse_arglist {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22117 | /* parse_arglist's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22118 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22119 | typedef struct fid_parse_arglist_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22120 | } fid_parse_arglist_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22121 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22122 | typedef cr_zero_size_type_t fid_parse_arglist_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22123 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22125 | /* parse_arglist's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22126 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22127 | typedef struct fid_parse_arglist_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22128 | struct fid_parse_arglist_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22129 | } fid_parse_arglist_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22130 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22131 | typedef cr_zero_size_type_t fid_parse_arglist_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22132 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22134 | #define CALL_PARSE_ARGLIST(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22135 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22136 | CR_CALL(fid_parse_arglist, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22137 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22138 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22140 | /* parse_member {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22141 | /* parse_member's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22142 | typedef struct fid_parse_member_arg { ast_off_t pos; } fid_parse_member_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22144 | /* parse_member's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22145 | typedef struct fid_parse_member_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22146 | struct fid_parse_member_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22147 | } fid_parse_member_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22148 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22149 | #define CALL_PARSE_MEMBER(_pos, _label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22150 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22151 | N.fid_parse_member.pos = (_pos); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22152 | CR_CALL(fid_parse_member, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22153 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22154 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22155 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22156 | /* parse_memberexpr {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22157 | /* parse_memberexpr's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22158 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22159 | typedef struct fid_parse_memberexpr_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22160 | } fid_parse_memberexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22161 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22162 | typedef cr_zero_size_type_t fid_parse_memberexpr_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22163 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22164 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22165 | /* parse_memberexpr's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22166 | typedef struct fid_parse_memberexpr_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22167 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22168 | struct fid_parse_memberexpr_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22169 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22170 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22171 | ast_off_t pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22172 | } fid_parse_memberexpr_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22173 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22174 | #define CALL_PARSE_MEMBEREXPR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22175 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22176 | CR_CALL(fid_parse_memberexpr, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22177 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22178 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22180 | /* parse_var {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22181 | /* parse_var's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22182 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22183 | typedef struct fid_parse_var_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22184 | } fid_parse_var_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22185 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22186 | typedef cr_zero_size_type_t fid_parse_var_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22187 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22189 | /* parse_var's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22190 | typedef struct fid_parse_var_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22191 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22192 | struct fid_parse_var_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22193 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22195 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22196 | } fid_parse_var_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22197 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22198 | #define CALL_PARSE_VAR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22199 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22200 | CR_CALL(fid_parse_var, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22201 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22202 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22204 | /* parse_prop {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22205 | /* parse_prop's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22206 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22207 | typedef struct fid_parse_prop_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22208 | } fid_parse_prop_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22209 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22210 | typedef cr_zero_size_type_t fid_parse_prop_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22211 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22213 | /* parse_prop's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22214 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22215 | typedef struct fid_parse_prop_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22216 | struct fid_parse_prop_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22217 | } fid_parse_prop_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22218 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22219 | typedef cr_zero_size_type_t fid_parse_prop_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22220 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22222 | #define CALL_PARSE_PROP(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22223 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22224 | CR_CALL(fid_parse_prop, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22225 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22226 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22228 | /* parse_dowhile {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22229 | /* parse_dowhile's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22230 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22231 | typedef struct fid_parse_dowhile_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22232 | } fid_parse_dowhile_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22233 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22234 | typedef cr_zero_size_type_t fid_parse_dowhile_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22235 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22237 | /* parse_dowhile's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22238 | typedef struct fid_parse_dowhile_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22239 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22240 | struct fid_parse_dowhile_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22241 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22243 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22244 | uint8_t saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22245 | } fid_parse_dowhile_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22246 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22247 | #define CALL_PARSE_DOWHILE(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22248 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22249 | CR_CALL(fid_parse_dowhile, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22250 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22251 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22253 | /* parse_for {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22254 | /* parse_for's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22255 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22256 | typedef struct fid_parse_for_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22257 | } fid_parse_for_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22258 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22259 | typedef cr_zero_size_type_t fid_parse_for_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22260 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22262 | /* parse_for's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22263 | typedef struct fid_parse_for_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22264 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22265 | struct fid_parse_for_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22266 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22268 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22269 | uint8_t saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22270 | } fid_parse_for_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22272 | #define CALL_PARSE_FOR(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22273 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22274 | CR_CALL(fid_parse_for, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22275 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22276 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22278 | /* parse_try {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22279 | /* parse_try's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22280 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22281 | typedef struct fid_parse_try_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22282 | } fid_parse_try_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22283 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22284 | typedef cr_zero_size_type_t fid_parse_try_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22285 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22286 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22287 | /* parse_try's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22288 | typedef struct fid_parse_try_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22289 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22290 | struct fid_parse_try_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22291 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22293 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22294 | uint8_t catch_or_finally; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22295 | } fid_parse_try_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22297 | #define CALL_PARSE_TRY(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22298 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22299 | CR_CALL(fid_parse_try, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22300 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22301 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22303 | /* parse_switch {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22304 | /* parse_switch's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22305 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22306 | typedef struct fid_parse_switch_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22307 | } fid_parse_switch_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22308 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22309 | typedef cr_zero_size_type_t fid_parse_switch_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22310 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22312 | /* parse_switch's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22313 | typedef struct fid_parse_switch_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22314 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22315 | struct fid_parse_switch_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22316 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22317 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22318 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22319 | int saved_in_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22320 | ast_off_t case_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22321 | } fid_parse_switch_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22322 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22323 | #define CALL_PARSE_SWITCH(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22324 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22325 | CR_CALL(fid_parse_switch, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22326 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22327 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22328 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22329 | /* parse_with {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22330 | /* parse_with's arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22331 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22332 | typedef struct fid_parse_with_arg { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22333 | } fid_parse_with_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22334 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22335 | typedef cr_zero_size_type_t fid_parse_with_arg_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22336 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22338 | /* parse_with's data on stack */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22339 | typedef struct fid_parse_with_locals { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22340 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22341 | struct fid_parse_with_arg arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22342 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22344 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22345 | } fid_parse_with_locals_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22347 | #define CALL_PARSE_WITH(_label) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22348 | do { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22349 | CR_CALL(fid_parse_with, _label); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22350 | } while (0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22351 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22352 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22353 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22355 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22356 | * Array of "function" descriptors. Each descriptor contains just a size |
Marko Mikulicic |
0:c0ecb8bf28eb | 22357 | * of "function"'s locals. |
Marko Mikulicic |
0:c0ecb8bf28eb | 22358 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22359 | static const struct cr_func_desc _fid_descrs[MY_FID_CNT] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22361 | /* fid_none */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22362 | {0}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22364 | /* fid_parse_script ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22365 | /* fid_parse_script */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22366 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22367 | /* fid_p_script_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22368 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22369 | /* fid_p_script_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22370 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22371 | /* fid_p_script_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22372 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22373 | /* fid_p_script_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22374 | {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22376 | /* fid_parse_use_strict ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22377 | /* fid_parse_use_strict */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22378 | {CR_LOCALS_SIZEOF(fid_parse_use_strict_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22380 | /* fid_parse_body ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22381 | /* fid_parse_body */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22382 | {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22383 | /* fid_p_body_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22384 | {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22385 | /* fid_p_body_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22386 | {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22388 | /* fid_parse_statement ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22389 | /* fid_parse_statement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22390 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22391 | /* fid_p_stat_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22392 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22393 | /* fid_p_stat_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22394 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22395 | /* fid_p_stat_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22396 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22397 | /* fid_p_stat_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22398 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22399 | /* fid_p_stat_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22400 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22401 | /* fid_p_stat_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22402 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22403 | /* fid_p_stat_7 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22404 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22405 | /* fid_p_stat_8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22406 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22407 | /* fid_p_stat_9 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22408 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22409 | /* fid_p_stat_10 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22410 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22411 | /* fid_p_stat_11 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22412 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22413 | /* fid_p_stat_12 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22414 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22415 | /* fid_p_stat_13 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22416 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22417 | /* fid_p_stat_14 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22418 | {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22419 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22420 | /* fid_parse_expression ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22421 | /* fid_parse_expression */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22422 | {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22423 | /* fid_p_expr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22424 | {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22426 | /* fid_parse_assign ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22427 | /* fid_parse_assign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22428 | {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22429 | /* fid_p_assign_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22430 | {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22432 | /* fid_parse_binary ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22433 | /* fid_parse_binary */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22434 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22435 | /* fid_p_binary_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22436 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22437 | /* fid_p_binary_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22438 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22439 | /* fid_p_binary_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22440 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22441 | /* fid_p_binary_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22442 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22443 | /* fid_p_binary_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22444 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22445 | /* fid_p_binary_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22446 | {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22448 | /* fid_parse_prefix ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22449 | /* fid_parse_prefix */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22450 | {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22451 | /* fid_p_prefix_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22452 | {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22453 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22454 | /* fid_parse_postfix ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22455 | /* fid_parse_postfix */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22456 | {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22457 | /* fid_p_postfix_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22458 | {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22460 | /* fid_parse_callexpr ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22461 | /* fid_parse_callexpr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22462 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22463 | /* fid_p_callexpr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22464 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22465 | /* fid_p_callexpr_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22466 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22467 | /* fid_p_callexpr_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22468 | {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22469 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22470 | /* fid_parse_newexpr ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22471 | /* fid_parse_newexpr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22472 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22473 | /* fid_p_newexpr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22474 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22475 | /* fid_p_newexpr_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22476 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22477 | /* fid_p_newexpr_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22478 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22479 | /* fid_p_newexpr_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22480 | {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22481 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22482 | /* fid_parse_terminal ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22483 | /* fid_parse_terminal */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22484 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22485 | /* fid_p_terminal_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22486 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22487 | /* fid_p_terminal_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22488 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22489 | /* fid_p_terminal_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22490 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22491 | /* fid_p_terminal_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22492 | {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22494 | /* fid_parse_block ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22495 | /* fid_parse_block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22496 | {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22497 | /* fid_p_block_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22498 | {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22499 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22500 | /* fid_parse_if ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22501 | /* fid_parse_if */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22502 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22503 | /* fid_p_if_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22504 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22505 | /* fid_p_if_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22506 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22507 | /* fid_p_if_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22508 | {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22510 | /* fid_parse_while ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22511 | /* fid_parse_while */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22512 | {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22513 | /* fid_p_while_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22514 | {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22515 | /* fid_p_while_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22516 | {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22518 | /* fid_parse_ident ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22519 | /* fid_parse_ident */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22520 | {CR_LOCALS_SIZEOF(fid_parse_ident_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22521 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22522 | /* fid_parse_ident_allow_reserved_words -------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22523 | /* fid_parse_ident_allow_reserved_words */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22524 | {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22525 | /* fid_p_ident_allow_reserved_words_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22526 | {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22527 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22528 | /* fid_parse_funcdecl ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22529 | /* fid_parse_funcdecl */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22530 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22531 | /* fid_p_funcdecl_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22532 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22533 | /* fid_p_funcdecl_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22534 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22535 | /* fid_p_funcdecl_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22536 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22537 | /* fid_p_funcdecl_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22538 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22539 | /* fid_p_funcdecl_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22540 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22541 | /* fid_p_funcdecl_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22542 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22543 | /* fid_p_funcdecl_7 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22544 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22545 | /* fid_p_funcdecl_8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22546 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22547 | /* fid_p_funcdecl_9 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22548 | {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22549 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22550 | /* fid_parse_arglist ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22551 | /* fid_parse_arglist */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22552 | {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22553 | /* fid_p_arglist_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22554 | {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22556 | /* fid_parse_member ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22557 | /* fid_parse_member */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22558 | {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22559 | /* fid_p_member_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22560 | {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22562 | /* fid_parse_memberexpr ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22563 | /* fid_parse_memberexpr */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22564 | {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22565 | /* fid_p_memberexpr_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22566 | {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22567 | /* fid_p_memberexpr_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22568 | {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22570 | /* fid_parse_var ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22571 | /* fid_parse_var */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22572 | {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22573 | /* fid_p_var_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22574 | {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22575 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22576 | /* fid_parse_prop ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22577 | /* fid_parse_prop */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22578 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22579 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22580 | /* fid_p_prop_1_getter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22581 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22582 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22583 | /* fid_p_prop_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22584 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22585 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22586 | /* fid_p_prop_3_setter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22587 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22588 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22589 | /* fid_p_prop_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22590 | {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22592 | /* fid_parse_dowhile ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22593 | /* fid_parse_dowhile */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22594 | {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22595 | /* fid_p_dowhile_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22596 | {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22597 | /* fid_p_dowhile_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22598 | {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22599 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22600 | /* fid_parse_for ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22601 | /* fid_parse_for */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22602 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22603 | /* fid_p_for_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22604 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22605 | /* fid_p_for_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22606 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22607 | /* fid_p_for_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22608 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22609 | /* fid_p_for_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22610 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22611 | /* fid_p_for_5 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22612 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22613 | /* fid_p_for_6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22614 | {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22616 | /* fid_parse_try ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22617 | /* fid_parse_try */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22618 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22619 | /* fid_p_try_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22620 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22621 | /* fid_p_try_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22622 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22623 | /* fid_p_try_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22624 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22625 | /* fid_p_try_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22626 | {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22627 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22628 | /* fid_parse_switch ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22629 | /* fid_parse_switch */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22630 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22631 | /* fid_p_switch_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22632 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22633 | /* fid_p_switch_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22634 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22635 | /* fid_p_switch_3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22636 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22637 | /* fid_p_switch_4 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22638 | {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22640 | /* fid_parse_with ----------------------------------------- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22641 | /* fid_parse_with */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22642 | {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22643 | /* fid_p_with_1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22644 | {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22645 | /* fid_p_with_2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22646 | {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22648 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22649 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22650 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22651 | * Union of arguments and return values for all existing "functions". |
Marko Mikulicic |
0:c0ecb8bf28eb | 22652 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 22653 | * Used as an accumulator when we call function, return from function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22654 | * yield, or resume. |
Marko Mikulicic |
0:c0ecb8bf28eb | 22655 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22656 | union user_arg_ret { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22657 | /* arguments to the next function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22658 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22659 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 22660 | fid_parse_script_arg_t fid_parse_script; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22661 | fid_parse_use_strict_arg_t fid_parse_use_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22662 | fid_parse_statement_arg_t fid_parse_statement; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22663 | fid_parse_expression_arg_t fid_parse_expression; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22664 | fid_parse_assign_arg_t fid_parse_assign; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22665 | fid_parse_prefix_arg_t fid_parse_prefix; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22666 | fid_parse_postfix_arg_t fid_parse_postfix; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22667 | fid_parse_callexpr_arg_t fid_parse_callexpr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22668 | fid_parse_newexpr_arg_t fid_parse_newexpr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22669 | fid_parse_terminal_arg_t fid_parse_terminal; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22670 | fid_parse_block_arg_t fid_parse_block; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22671 | fid_parse_if_arg_t fid_parse_if; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22672 | fid_parse_while_arg_t fid_parse_while; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22673 | fid_parse_ident_arg_t fid_parse_ident; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22674 | fid_parse_ident_allow_reserved_words_arg_t |
Marko Mikulicic |
0:c0ecb8bf28eb | 22675 | fid_parse_ident_allow_reserved_words; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22676 | fid_parse_arglist_arg_t fid_parse_arglist; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22677 | fid_parse_memberexpr_arg_t fid_parse_memberexpr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22678 | fid_parse_var_arg_t fid_parse_var; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22679 | fid_parse_prop_arg_t fid_parse_prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22680 | fid_parse_dowhile_arg_t fid_parse_dowhile; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22681 | fid_parse_for_arg_t fid_parse_for; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22682 | fid_parse_try_arg_t fid_parse_try; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22683 | fid_parse_switch_arg_t fid_parse_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22684 | fid_parse_with_arg_t fid_parse_with; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22685 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22686 | fid_parse_body_arg_t fid_parse_body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22687 | fid_parse_binary_arg_t fid_parse_binary; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22688 | fid_parse_funcdecl_arg_t fid_parse_funcdecl; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22689 | fid_parse_member_arg_t fid_parse_member; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22690 | } arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22691 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22692 | /* value returned from function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22693 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22694 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22695 | } ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22696 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22697 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22699 | static enum v7_tok next_tok(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22700 | int prev_line_no = v7->pstate.prev_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22701 | v7->pstate.prev_line_no = v7->pstate.line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22702 | v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22703 | v7->after_newline = prev_line_no != v7->pstate.line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22704 | v7->tok = v7->pstate.pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22705 | v7->cur_tok = get_tok(&v7->pstate.pc, v7->pstate.src_end, &v7->cur_tok_dbl, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22706 | v7->cur_tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22707 | v7->tok_len = v7->pstate.pc - v7->tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22708 | v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22709 | return v7->cur_tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22710 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22711 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22712 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22713 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22714 | * Assumes `offset` points to the byte right after a tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 22715 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22716 | static void insert_line_no_if_changed(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22717 | ast_off_t offset) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22718 | if (v7->pstate.prev_line_no != v7->line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22719 | v7->line_no = v7->pstate.prev_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22720 | ast_add_line_no(a, offset - 1, v7->line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22721 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22722 | #if V7_AST_FORCE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22723 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22724 | * This mode is needed for debug only: to make sure AST consumers correctly |
Marko Mikulicic |
0:c0ecb8bf28eb | 22725 | * consume all nodes with line numbers data encoded |
Marko Mikulicic |
0:c0ecb8bf28eb | 22726 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22727 | ast_add_line_no(a, offset - 1, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22728 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22729 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22731 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 22732 | static void insert_line_no_if_changed(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22733 | ast_off_t offset) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22734 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22735 | (void) a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22736 | (void) offset; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22737 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22738 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22739 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22740 | static ast_off_t insert_node(struct v7 *v7, struct ast *a, ast_off_t start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22741 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22742 | ast_off_t ret = ast_insert_node(a, start, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22743 | insert_line_no_if_changed(v7, a, ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22744 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22745 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22746 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22747 | static ast_off_t add_node(struct v7 *v7, struct ast *a, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22748 | return insert_node(v7, a, a->mbuf.len, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22751 | static ast_off_t insert_inlined_node(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22752 | ast_off_t start, enum ast_tag tag, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22753 | const char *name, size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22754 | ast_off_t ret = ast_insert_inlined_node(a, start, tag, name, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22755 | insert_line_no_if_changed(v7, a, ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22756 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22757 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22758 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22759 | static ast_off_t add_inlined_node(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22760 | enum ast_tag tag, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22761 | size_t len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22762 | return insert_inlined_node(v7, a, a->mbuf.len, tag, name, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22763 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22764 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22765 | static unsigned long get_column(const char *code, const char *pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22766 | const char *p = pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22767 | while (p > code && *p != '\n') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22768 | p--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22769 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22770 | return p == code ? pos - p : pos - (p + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22771 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22773 | static enum v7_err end_of_statement(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22774 | if (v7->cur_tok == TOK_SEMICOLON || v7->cur_tok == TOK_END_OF_INPUT || |
Marko Mikulicic |
0:c0ecb8bf28eb | 22775 | v7->cur_tok == TOK_CLOSE_CURLY || v7->after_newline) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22776 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22777 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22778 | return V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22779 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22780 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22781 | static enum v7_tok lookahead(const struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22782 | const char *s = v7->pstate.pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22783 | double d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22784 | return get_tok(&s, v7->pstate.src_end, &d, v7->cur_tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22786 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22787 | static int parse_optional(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22788 | enum v7_tok terminator) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22789 | if (v7->cur_tok != terminator) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22790 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22791 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22792 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22793 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22794 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22796 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22797 | * On ESP8266 'levels' declaration have to be outside of 'parse_binary' |
Marko Mikulicic |
0:c0ecb8bf28eb | 22798 | * in order to prevent reboot on return from this function |
Marko Mikulicic |
0:c0ecb8bf28eb | 22799 | * TODO(alashkin): understand why |
Marko Mikulicic |
0:c0ecb8bf28eb | 22800 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22801 | #define NONE \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22802 | { (enum v7_tok) 0, (enum v7_tok) 0, (enum ast_tag) 0 } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22804 | static const struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22805 | int len, left_to_right; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22806 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22807 | enum v7_tok start_tok, end_tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22808 | enum ast_tag start_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22809 | } parts[2]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22810 | } levels[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22811 | {1, 0, {{TOK_ASSIGN, TOK_URSHIFT_ASSIGN, AST_ASSIGN}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22812 | {1, 0, {{TOK_QUESTION, TOK_QUESTION, AST_COND}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22813 | {1, 1, {{TOK_LOGICAL_OR, TOK_LOGICAL_OR, AST_LOGICAL_OR}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22814 | {1, 1, {{TOK_LOGICAL_AND, TOK_LOGICAL_AND, AST_LOGICAL_AND}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22815 | {1, 1, {{TOK_OR, TOK_OR, AST_OR}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22816 | {1, 1, {{TOK_XOR, TOK_XOR, AST_XOR}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22817 | {1, 1, {{TOK_AND, TOK_AND, AST_AND}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22818 | {1, 1, {{TOK_EQ, TOK_NE_NE, AST_EQ}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22819 | {2, 1, {{TOK_LE, TOK_GT, AST_LE}, {TOK_IN, TOK_INSTANCEOF, AST_IN}}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22820 | {1, 1, {{TOK_LSHIFT, TOK_URSHIFT, AST_LSHIFT}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22821 | {1, 1, {{TOK_PLUS, TOK_MINUS, AST_ADD}, NONE}}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22822 | {1, 1, {{TOK_REM, TOK_DIV, AST_REM}, NONE}}}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22824 | enum cr_status parser_cr_exec(struct cr_ctx *p_ctx, struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 22825 | struct ast *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22826 | enum cr_status rc = CR_RES__OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22828 | _cr_iter_begin: |
Marko Mikulicic |
0:c0ecb8bf28eb | 22829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22830 | rc = cr_on_iter_begin(p_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22831 | if (rc != CR_RES__OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22832 | return rc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22833 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 22834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22835 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 22836 | * dispatcher switch: depending on the fid, jump to the corresponding label |
Marko Mikulicic |
0:c0ecb8bf28eb | 22837 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22838 | switch ((enum my_fid) CR_CURR_FUNC()) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22839 | CR_DEFINE_ENTRY_POINT(fid_none); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22841 | CR_DEFINE_ENTRY_POINT(fid_parse_script); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22842 | CR_DEFINE_ENTRY_POINT(fid_p_script_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22843 | CR_DEFINE_ENTRY_POINT(fid_p_script_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22844 | CR_DEFINE_ENTRY_POINT(fid_p_script_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22845 | CR_DEFINE_ENTRY_POINT(fid_p_script_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22846 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22847 | CR_DEFINE_ENTRY_POINT(fid_parse_use_strict); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22849 | CR_DEFINE_ENTRY_POINT(fid_parse_body); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22850 | CR_DEFINE_ENTRY_POINT(fid_p_body_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22851 | CR_DEFINE_ENTRY_POINT(fid_p_body_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22853 | CR_DEFINE_ENTRY_POINT(fid_parse_statement); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22854 | CR_DEFINE_ENTRY_POINT(fid_p_stat_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22855 | CR_DEFINE_ENTRY_POINT(fid_p_stat_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22856 | CR_DEFINE_ENTRY_POINT(fid_p_stat_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22857 | CR_DEFINE_ENTRY_POINT(fid_p_stat_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22858 | CR_DEFINE_ENTRY_POINT(fid_p_stat_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22859 | CR_DEFINE_ENTRY_POINT(fid_p_stat_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22860 | CR_DEFINE_ENTRY_POINT(fid_p_stat_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22861 | CR_DEFINE_ENTRY_POINT(fid_p_stat_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22862 | CR_DEFINE_ENTRY_POINT(fid_p_stat_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22863 | CR_DEFINE_ENTRY_POINT(fid_p_stat_10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22864 | CR_DEFINE_ENTRY_POINT(fid_p_stat_11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22865 | CR_DEFINE_ENTRY_POINT(fid_p_stat_12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22866 | CR_DEFINE_ENTRY_POINT(fid_p_stat_13); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22867 | CR_DEFINE_ENTRY_POINT(fid_p_stat_14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22869 | CR_DEFINE_ENTRY_POINT(fid_parse_expression); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22870 | CR_DEFINE_ENTRY_POINT(fid_p_expr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22871 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22872 | CR_DEFINE_ENTRY_POINT(fid_parse_assign); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22873 | CR_DEFINE_ENTRY_POINT(fid_p_assign_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22875 | CR_DEFINE_ENTRY_POINT(fid_parse_binary); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22876 | CR_DEFINE_ENTRY_POINT(fid_p_binary_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22877 | CR_DEFINE_ENTRY_POINT(fid_p_binary_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22878 | CR_DEFINE_ENTRY_POINT(fid_p_binary_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22879 | CR_DEFINE_ENTRY_POINT(fid_p_binary_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22880 | CR_DEFINE_ENTRY_POINT(fid_p_binary_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22882 | CR_DEFINE_ENTRY_POINT(fid_parse_prefix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22883 | CR_DEFINE_ENTRY_POINT(fid_p_prefix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22885 | CR_DEFINE_ENTRY_POINT(fid_parse_postfix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22886 | CR_DEFINE_ENTRY_POINT(fid_p_postfix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22888 | CR_DEFINE_ENTRY_POINT(fid_parse_callexpr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22889 | CR_DEFINE_ENTRY_POINT(fid_p_callexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22890 | CR_DEFINE_ENTRY_POINT(fid_p_callexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22891 | CR_DEFINE_ENTRY_POINT(fid_p_callexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22893 | CR_DEFINE_ENTRY_POINT(fid_parse_newexpr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22894 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22895 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22896 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22897 | CR_DEFINE_ENTRY_POINT(fid_p_newexpr_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22898 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22899 | CR_DEFINE_ENTRY_POINT(fid_parse_terminal); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22900 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22901 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22902 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22903 | CR_DEFINE_ENTRY_POINT(fid_p_terminal_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22905 | CR_DEFINE_ENTRY_POINT(fid_parse_block); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22906 | CR_DEFINE_ENTRY_POINT(fid_p_block_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22907 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22908 | CR_DEFINE_ENTRY_POINT(fid_parse_if); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22909 | CR_DEFINE_ENTRY_POINT(fid_p_if_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22910 | CR_DEFINE_ENTRY_POINT(fid_p_if_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22911 | CR_DEFINE_ENTRY_POINT(fid_p_if_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22913 | CR_DEFINE_ENTRY_POINT(fid_parse_while); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22914 | CR_DEFINE_ENTRY_POINT(fid_p_while_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22915 | CR_DEFINE_ENTRY_POINT(fid_p_while_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22917 | CR_DEFINE_ENTRY_POINT(fid_parse_ident); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22918 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22919 | CR_DEFINE_ENTRY_POINT(fid_parse_ident_allow_reserved_words); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22920 | CR_DEFINE_ENTRY_POINT(fid_p_ident_arw_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22922 | CR_DEFINE_ENTRY_POINT(fid_parse_funcdecl); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22923 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22924 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22925 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22926 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22927 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22928 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22929 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22930 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22931 | CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22932 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22933 | CR_DEFINE_ENTRY_POINT(fid_parse_arglist); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22934 | CR_DEFINE_ENTRY_POINT(fid_p_arglist_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22936 | CR_DEFINE_ENTRY_POINT(fid_parse_member); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22937 | CR_DEFINE_ENTRY_POINT(fid_p_member_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22938 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22939 | CR_DEFINE_ENTRY_POINT(fid_parse_memberexpr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22940 | CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22941 | CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22942 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22943 | CR_DEFINE_ENTRY_POINT(fid_parse_var); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22944 | CR_DEFINE_ENTRY_POINT(fid_p_var_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22946 | CR_DEFINE_ENTRY_POINT(fid_parse_prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22947 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22948 | CR_DEFINE_ENTRY_POINT(fid_p_prop_1_getter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22949 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22950 | CR_DEFINE_ENTRY_POINT(fid_p_prop_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22951 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 22952 | CR_DEFINE_ENTRY_POINT(fid_p_prop_3_setter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22953 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 22954 | CR_DEFINE_ENTRY_POINT(fid_p_prop_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22955 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22956 | CR_DEFINE_ENTRY_POINT(fid_parse_dowhile); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22957 | CR_DEFINE_ENTRY_POINT(fid_p_dowhile_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22958 | CR_DEFINE_ENTRY_POINT(fid_p_dowhile_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22960 | CR_DEFINE_ENTRY_POINT(fid_parse_for); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22961 | CR_DEFINE_ENTRY_POINT(fid_p_for_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22962 | CR_DEFINE_ENTRY_POINT(fid_p_for_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22963 | CR_DEFINE_ENTRY_POINT(fid_p_for_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22964 | CR_DEFINE_ENTRY_POINT(fid_p_for_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22965 | CR_DEFINE_ENTRY_POINT(fid_p_for_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22966 | CR_DEFINE_ENTRY_POINT(fid_p_for_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22968 | CR_DEFINE_ENTRY_POINT(fid_parse_try); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22969 | CR_DEFINE_ENTRY_POINT(fid_p_try_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22970 | CR_DEFINE_ENTRY_POINT(fid_p_try_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22971 | CR_DEFINE_ENTRY_POINT(fid_p_try_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22972 | CR_DEFINE_ENTRY_POINT(fid_p_try_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22974 | CR_DEFINE_ENTRY_POINT(fid_parse_switch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22975 | CR_DEFINE_ENTRY_POINT(fid_p_switch_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22976 | CR_DEFINE_ENTRY_POINT(fid_p_switch_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22977 | CR_DEFINE_ENTRY_POINT(fid_p_switch_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22978 | CR_DEFINE_ENTRY_POINT(fid_p_switch_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22980 | CR_DEFINE_ENTRY_POINT(fid_parse_with); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22981 | CR_DEFINE_ENTRY_POINT(fid_p_with_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22982 | CR_DEFINE_ENTRY_POINT(fid_p_with_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22983 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22984 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 22985 | /* should never be here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22986 | printf("fatal: wrong func id: %d", CR_CURR_FUNC()); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22987 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22988 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22989 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22990 | /* static enum v7_err parse_script(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 22991 | fid_parse_script : |
Marko Mikulicic |
0:c0ecb8bf28eb | 22992 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 22993 | #define L CR_CUR_LOCALS_PT(fid_parse_script_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 22994 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 22995 | L->start = add_node(v7, a, AST_SCRIPT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 22996 | L->outer_last_var_node = v7->last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22997 | L->saved_in_strict = v7->pstate.in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 22998 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 22999 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23000 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23001 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23002 | CR_TRY(fid_p_script_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23003 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23004 | CALL_PARSE_USE_STRICT(fid_p_script_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23005 | v7->pstate.in_strict = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23006 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23007 | CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_script_1, fid_p_script_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23008 | CR_ENDCATCH(fid_p_script_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23010 | CALL_PARSE_BODY(TOK_END_OF_INPUT, fid_p_script_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23011 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23012 | v7->pstate.in_strict = L->saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23013 | v7->last_var_node = L->outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23015 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23016 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23018 | /* static enum v7_err parse_use_strict(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23019 | fid_parse_use_strict : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23020 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23021 | #define L CR_CUR_LOCALS_PT(fid_parse_use_strict_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23022 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23023 | if (v7->cur_tok == TOK_STRING_LITERAL && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23024 | (strncmp(v7->tok, "\"use strict\"", v7->tok_len) == 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 23025 | strncmp(v7->tok, "'use strict'", v7->tok_len) == 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23026 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23027 | add_node(v7, a, AST_USE_STRICT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23028 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23029 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23030 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23031 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23032 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23033 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23034 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23035 | * static enum v7_err parse_body(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23036 | * enum v7_tok end) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23037 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23038 | fid_parse_body : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23039 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23040 | #define L CR_CUR_LOCALS_PT(fid_parse_body_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23041 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23042 | while (v7->cur_tok != L->arg.end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23043 | if (ACCEPT(TOK_FUNCTION)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23044 | if (v7->cur_tok != TOK_IDENTIFIER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23045 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23046 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23047 | L->start = add_node(v7, a, AST_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23048 | ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23049 | /* zero out var node pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23050 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23051 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23052 | add_inlined_node(v7, a, AST_FUNC_DECL, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23054 | CALL_PARSE_FUNCDECL(1, 0, fid_p_body_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23055 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23056 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23057 | CALL_PARSE_STATEMENT(fid_p_body_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23058 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23059 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23060 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23061 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23063 | /* static enum v7_err parse_statement(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23064 | fid_parse_statement : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23065 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23066 | #define L CR_CUR_LOCALS_PT(fid_parse_statement_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23067 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23068 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23069 | case TOK_SEMICOLON: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23070 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23071 | /* empty statement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23072 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23073 | case TOK_OPEN_CURLY: /* block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23074 | CALL_PARSE_BLOCK(fid_p_stat_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23075 | /* returning because no semicolon required */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23076 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23077 | case TOK_IF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23078 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23079 | CALL_PARSE_IF(fid_p_stat_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23080 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23081 | case TOK_WHILE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23082 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23083 | CALL_PARSE_WHILE(fid_p_stat_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23084 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23085 | case TOK_DO: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23086 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23087 | CALL_PARSE_DOWHILE(fid_p_stat_10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23088 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23089 | case TOK_FOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23090 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23091 | CALL_PARSE_FOR(fid_p_stat_11); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23092 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23093 | case TOK_TRY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23094 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23095 | CALL_PARSE_TRY(fid_p_stat_12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23096 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23097 | case TOK_SWITCH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23098 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23099 | CALL_PARSE_SWITCH(fid_p_stat_13); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23100 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23101 | case TOK_WITH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23102 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23103 | CALL_PARSE_WITH(fid_p_stat_14); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23104 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23105 | case TOK_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23106 | if (!(v7->pstate.in_loop || v7->pstate.in_switch)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23107 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23108 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23109 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23110 | PARSE_WITH_OPT_ARG(AST_BREAK, AST_LABELED_BREAK, CALL_PARSE_IDENT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23111 | fid_p_stat_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23112 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23113 | case TOK_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23114 | if (!v7->pstate.in_loop) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23115 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23116 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23117 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23118 | PARSE_WITH_OPT_ARG(AST_CONTINUE, AST_LABELED_CONTINUE, CALL_PARSE_IDENT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23119 | fid_p_stat_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23120 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23121 | case TOK_RETURN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23122 | if (!v7->pstate.in_function) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23123 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23124 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23125 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23126 | PARSE_WITH_OPT_ARG(AST_RETURN, AST_VALUE_RETURN, CALL_PARSE_EXPRESSION, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23127 | fid_p_stat_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23128 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23129 | case TOK_THROW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23130 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23131 | add_node(v7, a, AST_THROW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23132 | CALL_PARSE_EXPRESSION(fid_p_stat_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23133 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23134 | case TOK_DEBUGGER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23135 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23136 | add_node(v7, a, AST_DEBUGGER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23137 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23138 | case TOK_VAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23139 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23140 | CALL_PARSE_VAR(fid_p_stat_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23141 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23142 | case TOK_IDENTIFIER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23143 | if (lookahead(v7) == TOK_COLON) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23144 | add_inlined_node(v7, a, AST_LABEL, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23145 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23146 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23147 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23148 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23149 | /* fall through */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23150 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23151 | CALL_PARSE_EXPRESSION(fid_p_stat_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23152 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23153 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23154 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23155 | if (end_of_statement(v7) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23156 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23157 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23158 | ACCEPT(TOK_SEMICOLON); /* swallow optional semicolon */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23159 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23160 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23162 | /* static enum v7_err parse_expression(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23163 | fid_parse_expression : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23164 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23165 | #define L CR_CUR_LOCALS_PT(fid_parse_expression_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23166 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23167 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23168 | L->group = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23169 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23170 | CALL_PARSE_ASSIGN(fid_p_expr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23171 | if (ACCEPT(TOK_COMMA)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23172 | L->group = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23173 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23174 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23175 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23176 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23177 | if (L->group) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23178 | insert_node(v7, a, L->pos, AST_SEQ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23179 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23180 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23181 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23182 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23183 | /* static enum v7_err parse_assign(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23184 | fid_parse_assign : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23185 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23186 | #define L CR_CUR_LOCALS_PT(fid_parse_assign_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23187 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23188 | CALL_PARSE_BINARY(0, a->mbuf.len, fid_p_assign_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23189 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23190 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23192 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23193 | * static enum v7_err parse_binary(struct v7 *v7, struct ast *a, int level, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23194 | * ast_off_t pos) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23195 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23196 | #if 1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 23197 | fid_parse_binary : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23198 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23199 | #define L CR_CUR_LOCALS_PT(fid_parse_binary_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23200 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23201 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23202 | * Note: we use macro CUR_POS instead of a local variable, since this |
Marko Mikulicic |
0:c0ecb8bf28eb | 23203 | * function is called really a lot, so, each byte on stack frame counts. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23204 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 23205 | * It will work a bit slower of course, but slowness is not a problem |
Marko Mikulicic |
0:c0ecb8bf28eb | 23206 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23207 | #define CUR_POS ((L->level > L->arg.min_level) ? L->saved_mbuf_len : L->arg.pos) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23208 | L->saved_mbuf_len = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23210 | CALL_PARSE_PREFIX(fid_p_binary_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23211 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23212 | for (L->level = (int) ARRAY_SIZE(levels) - 1; L->level >= L->arg.min_level; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23213 | L->level--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23214 | for (L->i = 0; L->i < levels[L->level].len; L->i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23215 | L->tok = levels[L->level].parts[L->i].start_tok; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23216 | L->ast = levels[L->level].parts[L->i].start_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23217 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23218 | if (v7->pstate.inhibit_in && L->tok == TOK_IN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23219 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23220 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23222 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23223 | * Ternary operator sits in the middle of the binary operator |
Marko Mikulicic |
0:c0ecb8bf28eb | 23224 | * precedence chain. Deal with it as an exception and don't break |
Marko Mikulicic |
0:c0ecb8bf28eb | 23225 | * the chain. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23226 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23227 | if (L->tok == TOK_QUESTION && v7->cur_tok == TOK_QUESTION) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23228 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23229 | CALL_PARSE_ASSIGN(fid_p_binary_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23230 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23231 | CALL_PARSE_ASSIGN(fid_p_binary_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23232 | insert_node(v7, a, CUR_POS, AST_COND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23233 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23234 | } else if (ACCEPT(L->tok)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23235 | if (levels[L->level].left_to_right) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23236 | insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23237 | CALL_PARSE_BINARY(L->level, CUR_POS, fid_p_binary_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23238 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23239 | CALL_PARSE_BINARY(L->level, a->mbuf.len, fid_p_binary_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23240 | insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23241 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23242 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23243 | } while (L->ast = (enum ast_tag)(L->ast + 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 23244 | L->tok < levels[L->level].parts[L->i].end_tok && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23245 | (L->tok = (enum v7_tok)(L->tok + 1))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23246 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23247 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23249 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23250 | #undef CUR_POS |
Marko Mikulicic |
0:c0ecb8bf28eb | 23251 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23252 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23253 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23254 | /* enum v7_err parse_prefix(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23255 | fid_parse_prefix : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23256 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23257 | #define L CR_CUR_LOCALS_PT(fid_parse_prefix_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23258 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23259 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23260 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23261 | case TOK_PLUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23262 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23263 | add_node(v7, a, AST_POSITIVE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23264 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23265 | case TOK_MINUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23266 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23267 | add_node(v7, a, AST_NEGATIVE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23268 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23269 | case TOK_PLUS_PLUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23270 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23271 | add_node(v7, a, AST_PREINC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23272 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23273 | case TOK_MINUS_MINUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23274 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23275 | add_node(v7, a, AST_PREDEC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23276 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23277 | case TOK_TILDA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23278 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23279 | add_node(v7, a, AST_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23280 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23281 | case TOK_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23282 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23283 | add_node(v7, a, AST_LOGICAL_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23284 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23285 | case TOK_VOID: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23286 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23287 | add_node(v7, a, AST_VOID); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23288 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23289 | case TOK_DELETE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23290 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23291 | add_node(v7, a, AST_DELETE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23292 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23293 | case TOK_TYPEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23294 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23295 | add_node(v7, a, AST_TYPEOF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23296 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23297 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23298 | CALL_PARSE_POSTFIX(fid_p_prefix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23299 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23302 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23303 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23304 | /* static enum v7_err parse_postfix(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23305 | fid_parse_postfix : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23306 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23307 | #define L CR_CUR_LOCALS_PT(fid_parse_postfix_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23308 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23309 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23310 | CALL_PARSE_CALLEXPR(fid_p_postfix_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23311 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23312 | if (v7->after_newline) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23313 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23314 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23315 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23316 | case TOK_PLUS_PLUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23317 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23318 | insert_node(v7, a, L->pos, AST_POSTINC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23319 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23320 | case TOK_MINUS_MINUS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23321 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23322 | insert_node(v7, a, L->pos, AST_POSTDEC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23323 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23324 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23325 | break; /* nothing */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23326 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23327 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23328 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23330 | /* static enum v7_err parse_callexpr(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23331 | fid_parse_callexpr : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23332 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23333 | #define L CR_CUR_LOCALS_PT(fid_parse_callexpr_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23334 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23335 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23336 | CALL_PARSE_NEWEXPR(fid_p_callexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23338 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23339 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23340 | case TOK_DOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23341 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23342 | CALL_PARSE_MEMBER(L->pos, fid_p_callexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23343 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23344 | case TOK_OPEN_PAREN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23345 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23346 | CALL_PARSE_ARGLIST(fid_p_callexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23347 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23348 | insert_node(v7, a, L->pos, AST_CALL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23349 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23350 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23351 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23352 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23354 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23356 | /* static enum v7_err parse_newexpr(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23357 | fid_parse_newexpr : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23358 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23359 | #define L CR_CUR_LOCALS_PT(fid_parse_newexpr_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23360 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23361 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23362 | case TOK_NEW: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23363 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23364 | L->start = add_node(v7, a, AST_NEW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23365 | CALL_PARSE_MEMBEREXPR(fid_p_newexpr_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23366 | if (ACCEPT(TOK_OPEN_PAREN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23367 | CALL_PARSE_ARGLIST(fid_p_newexpr_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23368 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23370 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23371 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23372 | case TOK_FUNCTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23373 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23374 | CALL_PARSE_FUNCDECL(0, 0, fid_p_newexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23375 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23376 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23377 | CALL_PARSE_TERMINAL(fid_p_newexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23378 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23380 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23381 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23383 | /* static enum v7_err parse_terminal(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23384 | fid_parse_terminal : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23385 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23386 | #define L CR_CUR_LOCALS_PT(fid_parse_terminal_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23387 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23388 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23389 | case TOK_OPEN_PAREN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23390 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23391 | CALL_PARSE_EXPRESSION(fid_p_terminal_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23392 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23393 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23394 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23395 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23396 | L->start = add_node(v7, a, AST_ARRAY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23397 | while (v7->cur_tok != TOK_CLOSE_BRACKET) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23398 | if (v7->cur_tok == TOK_COMMA) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23399 | /* Array literals allow missing elements, e.g. [,,1,] */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23400 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23401 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23402 | CALL_PARSE_ASSIGN(fid_p_terminal_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23403 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23404 | ACCEPT(TOK_COMMA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23405 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23406 | EXPECT(TOK_CLOSE_BRACKET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23407 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23408 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23409 | case TOK_OPEN_CURLY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23410 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23411 | L->start = add_node(v7, a, AST_OBJECT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23412 | if (v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23413 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23414 | if (v7->cur_tok == TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23415 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23417 | CALL_PARSE_PROP(fid_p_terminal_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23418 | } while (ACCEPT(TOK_COMMA)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23419 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23420 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23421 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23422 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23423 | case TOK_THIS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23424 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23425 | add_node(v7, a, AST_THIS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23426 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23427 | case TOK_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23428 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23429 | add_node(v7, a, AST_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23430 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23431 | case TOK_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23432 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23433 | add_node(v7, a, AST_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23434 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23435 | case TOK_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23436 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23437 | add_node(v7, a, AST_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23438 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23439 | case TOK_STRING_LITERAL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23440 | add_inlined_node(v7, a, AST_STRING, v7->tok + 1, v7->tok_len - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23441 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23442 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23443 | case TOK_NUMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23444 | add_inlined_node(v7, a, AST_NUM, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23445 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23446 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23447 | case TOK_REGEX_LITERAL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23448 | add_inlined_node(v7, a, AST_REGEX, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23449 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23450 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23451 | case TOK_IDENTIFIER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23452 | if (v7->tok_len == 9 && strncmp(v7->tok, "undefined", v7->tok_len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23453 | add_node(v7, a, AST_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23454 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23455 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23456 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23457 | /* fall through */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23458 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23459 | CALL_PARSE_IDENT(fid_p_terminal_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23461 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23462 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23464 | /* static enum v7_err parse_block(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23465 | fid_parse_block : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23466 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23467 | #define L CR_CUR_LOCALS_PT(fid_parse_block_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23468 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23469 | EXPECT(TOK_OPEN_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23470 | CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_block_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23471 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23472 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23473 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23474 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23475 | /* static enum v7_err parse_if(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23476 | fid_parse_if : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23477 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23478 | #define L CR_CUR_LOCALS_PT(fid_parse_if_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23479 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23480 | L->start = add_node(v7, a, AST_IF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23481 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23482 | CALL_PARSE_EXPRESSION(fid_p_if_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23483 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23484 | CALL_PARSE_STATEMENT(fid_p_if_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23485 | ast_set_skip(a, L->start, AST_END_IF_TRUE_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23486 | if (ACCEPT(TOK_ELSE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23487 | CALL_PARSE_STATEMENT(fid_p_if_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23488 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23489 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23490 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23491 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23492 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23493 | /* static enum v7_err parse_while(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23494 | fid_parse_while : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23495 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23496 | #define L CR_CUR_LOCALS_PT(fid_parse_while_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23497 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23498 | L->start = add_node(v7, a, AST_WHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23499 | L->saved_in_loop = v7->pstate.in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23500 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23501 | CALL_PARSE_EXPRESSION(fid_p_while_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23502 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23503 | v7->pstate.in_loop = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23504 | CALL_PARSE_STATEMENT(fid_p_while_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23505 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23506 | v7->pstate.in_loop = L->saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23507 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23508 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23509 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23510 | /* static enum v7_err parse_ident(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23511 | fid_parse_ident : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23512 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23513 | #define L CR_CUR_LOCALS_PT(fid_parse_ident_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23514 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23515 | if (v7->cur_tok == TOK_IDENTIFIER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23516 | add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23517 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23518 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23519 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23520 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23521 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23523 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23524 | * static enum v7_err parse_ident_allow_reserved_words(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23525 | * struct ast *a) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23526 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 23527 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23528 | fid_parse_ident_allow_reserved_words : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23529 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23530 | #define L CR_CUR_LOCALS_PT(fid_parse_ident_allow_reserved_words_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23531 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23532 | /* Allow reserved words as property names. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23533 | if (is_reserved_word_token(v7->cur_tok)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23534 | add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23535 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23536 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23537 | CALL_PARSE_IDENT(fid_p_ident_arw_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23538 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23539 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23540 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23542 | /* static enum v7_err parse_funcdecl(struct v7 *, struct ast *, int, int) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23543 | fid_parse_funcdecl : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23544 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23545 | #define L CR_CUR_LOCALS_PT(fid_parse_funcdecl_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23546 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23547 | L->start = add_node(v7, a, AST_FUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23548 | L->outer_last_var_node = v7->last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23549 | L->saved_in_function = v7->pstate.in_function; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23550 | L->saved_in_strict = v7->pstate.in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23552 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23553 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23555 | CR_TRY(fid_p_funcdecl_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23556 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23557 | if (L->arg.reserved_name) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23558 | CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(fid_p_funcdecl_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23559 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23560 | CALL_PARSE_IDENT(fid_p_funcdecl_9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23561 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23562 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23563 | CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_2, fid_p_funcdecl_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23564 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23565 | if (L->arg.require_named) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23566 | /* function name is required, so, rethrow SYNTAX ERROR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23567 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23568 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23569 | /* it's ok not to have a function name, just insert NOP */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23570 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23571 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23572 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23573 | CR_ENDCATCH(fid_p_funcdecl_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23575 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23576 | CALL_PARSE_ARGLIST(fid_p_funcdecl_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23577 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23578 | ast_set_skip(a, L->start, AST_FUNC_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23579 | v7->pstate.in_function = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23580 | EXPECT(TOK_OPEN_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23582 | CR_TRY(fid_p_funcdecl_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23583 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23584 | CALL_PARSE_USE_STRICT(fid_p_funcdecl_7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23585 | v7->pstate.in_strict = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23586 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23587 | CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_5, fid_p_funcdecl_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23588 | CR_ENDCATCH(fid_p_funcdecl_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23589 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23590 | CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_funcdecl_8); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23591 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23592 | v7->pstate.in_strict = L->saved_in_strict; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23593 | v7->pstate.in_function = L->saved_in_function; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23594 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23595 | v7->last_var_node = L->outer_last_var_node; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23597 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23598 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23599 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23600 | /* static enum v7_err parse_arglist(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23601 | fid_parse_arglist : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23602 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23603 | #define L CR_CUR_LOCALS_PT(fid_parse_arglist_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23604 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23605 | if (v7->cur_tok != TOK_CLOSE_PAREN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23606 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23607 | CALL_PARSE_ASSIGN(fid_p_arglist_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23608 | } while (ACCEPT(TOK_COMMA)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23609 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23610 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23611 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23612 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23613 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23614 | * static enum v7_err parse_member(struct v7 *v7, struct ast *a, ast_off_t pos) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23615 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23616 | fid_parse_member : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23617 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23618 | #define L CR_CUR_LOCALS_PT(fid_parse_member_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23619 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23620 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23621 | case TOK_DOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23622 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23623 | /* Allow reserved words as member identifiers */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23624 | if (is_reserved_word_token(v7->cur_tok) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 23625 | v7->cur_tok == TOK_IDENTIFIER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23626 | insert_inlined_node(v7, a, L->arg.pos, AST_MEMBER, v7->tok, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23627 | v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23628 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23629 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23630 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23631 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23632 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23633 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23634 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23635 | CALL_PARSE_EXPRESSION(fid_p_member_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23636 | EXPECT(TOK_CLOSE_BRACKET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23637 | insert_node(v7, a, L->arg.pos, AST_INDEX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23638 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23639 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23640 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23642 | /* not necessary, but let it be anyway */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23643 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23644 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23645 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23646 | /* static enum v7_err parse_memberexpr(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23647 | fid_parse_memberexpr : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23648 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23649 | #define L CR_CUR_LOCALS_PT(fid_parse_memberexpr_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23650 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23651 | L->pos = a->mbuf.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23652 | CALL_PARSE_NEWEXPR(fid_p_memberexpr_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23653 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23654 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23655 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23656 | case TOK_DOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23657 | case TOK_OPEN_BRACKET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23658 | CALL_PARSE_MEMBER(L->pos, fid_p_memberexpr_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23659 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23660 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23661 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23662 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23663 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23664 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23666 | /* static enum v7_err parse_var(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23667 | fid_parse_var : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23668 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23669 | #define L CR_CUR_LOCALS_PT(fid_parse_var_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23670 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23671 | L->start = add_node(v7, a, AST_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23672 | ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23673 | /* zero out var node pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23674 | ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23675 | v7->last_var_node = L->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23676 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23677 | add_inlined_node(v7, a, AST_VAR_DECL, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23678 | EXPECT(TOK_IDENTIFIER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23679 | if (ACCEPT(TOK_ASSIGN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23680 | CALL_PARSE_ASSIGN(fid_p_var_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23681 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23682 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23683 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23684 | } while (ACCEPT(TOK_COMMA)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23685 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23686 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23687 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23689 | /* static enum v7_err parse_prop(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23690 | fid_parse_prop : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23691 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23692 | #define L CR_CUR_LOCALS_PT(fid_parse_prop_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23693 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23694 | #ifdef V7_ENABLE_JS_GETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 23695 | if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23696 | strncmp(v7->tok, "get", v7->tok_len) == 0 && lookahead(v7) != TOK_COLON) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23697 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23698 | add_node(v7, a, AST_GETTER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23699 | CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_1_getter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23700 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 23701 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23702 | if (v7->cur_tok == TOK_IDENTIFIER && lookahead(v7) == TOK_OPEN_PAREN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23703 | /* ecmascript 6 feature */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23704 | CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23705 | #ifdef V7_ENABLE_JS_SETTERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 23706 | } else if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23707 | strncmp(v7->tok, "set", v7->tok_len) == 0 && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23708 | lookahead(v7) != TOK_COLON) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23709 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23710 | add_node(v7, a, AST_SETTER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23711 | CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_3_setter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23712 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23713 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23714 | /* Allow reserved words as property names. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23715 | if (is_reserved_word_token(v7->cur_tok) || v7->cur_tok == TOK_IDENTIFIER || |
Marko Mikulicic |
0:c0ecb8bf28eb | 23716 | v7->cur_tok == TOK_NUMBER) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23717 | add_inlined_node(v7, a, AST_PROP, v7->tok, v7->tok_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23718 | } else if (v7->cur_tok == TOK_STRING_LITERAL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23719 | add_inlined_node(v7, a, AST_PROP, v7->tok + 1, v7->tok_len - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23720 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23721 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23722 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23723 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23724 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23725 | CALL_PARSE_ASSIGN(fid_p_prop_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23726 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23727 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23728 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23730 | /* static enum v7_err parse_dowhile(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23731 | fid_parse_dowhile : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23732 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23733 | #define L CR_CUR_LOCALS_PT(fid_parse_dowhile_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23734 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23735 | L->start = add_node(v7, a, AST_DOWHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23736 | L->saved_in_loop = v7->pstate.in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23737 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23738 | v7->pstate.in_loop = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23739 | CALL_PARSE_STATEMENT(fid_p_dowhile_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23740 | v7->pstate.in_loop = L->saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23741 | ast_set_skip(a, L->start, AST_DO_WHILE_COND_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23742 | EXPECT(TOK_WHILE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23743 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23744 | CALL_PARSE_EXPRESSION(fid_p_dowhile_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23745 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23746 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23747 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23748 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23749 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23750 | /* static enum v7_err parse_for(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23751 | fid_parse_for : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23752 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23753 | #define L CR_CUR_LOCALS_PT(fid_parse_for_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23754 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23755 | /* TODO(mkm): for of, for each in */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23756 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23757 | ast_off_t start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23758 | int saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23759 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23760 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23761 | L->start = add_node(v7, a, AST_FOR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23762 | L->saved_in_loop = v7->pstate.in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23764 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23765 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23766 | if (parse_optional(v7, a, TOK_SEMICOLON)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23767 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23768 | * TODO(mkm): make this reentrant otherwise this pearl won't parse: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23769 | * for((function(){return 1 in o.a ? o : x})().a in [1,2,3]) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23770 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23771 | v7->pstate.inhibit_in = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23772 | if (ACCEPT(TOK_VAR)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23773 | CALL_PARSE_VAR(fid_p_for_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23774 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23775 | CALL_PARSE_EXPRESSION(fid_p_for_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23776 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23777 | v7->pstate.inhibit_in = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23779 | if (ACCEPT(TOK_IN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23780 | CALL_PARSE_EXPRESSION(fid_p_for_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23781 | add_node(v7, a, AST_NOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23782 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23783 | * Assumes that for and for in have the same AST format which is |
Marko Mikulicic |
0:c0ecb8bf28eb | 23784 | * suboptimal but avoids the need of fixing up the var offset chain. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23785 | * TODO(mkm) improve this |
Marko Mikulicic |
0:c0ecb8bf28eb | 23786 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23787 | ast_modify_tag(a, L->start - 1, AST_FOR_IN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23788 | goto for_loop_body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23789 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23790 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23792 | EXPECT(TOK_SEMICOLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23793 | if (parse_optional(v7, a, TOK_SEMICOLON)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23794 | CALL_PARSE_EXPRESSION(fid_p_for_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23795 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23796 | EXPECT(TOK_SEMICOLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23797 | if (parse_optional(v7, a, TOK_CLOSE_PAREN)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23798 | CALL_PARSE_EXPRESSION(fid_p_for_5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23799 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23800 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23801 | for_loop_body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23802 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23803 | ast_set_skip(a, L->start, AST_FOR_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23804 | v7->pstate.in_loop = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23805 | CALL_PARSE_STATEMENT(fid_p_for_6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23806 | v7->pstate.in_loop = L->saved_in_loop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23807 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23808 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23809 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23810 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23811 | /* static enum v7_err parse_try(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23812 | fid_parse_try : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23813 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23814 | #define L CR_CUR_LOCALS_PT(fid_parse_try_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23815 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23816 | L->start = add_node(v7, a, AST_TRY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23817 | L->catch_or_finally = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23818 | CALL_PARSE_BLOCK(fid_p_try_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23819 | ast_set_skip(a, L->start, AST_TRY_CATCH_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23820 | if (ACCEPT(TOK_CATCH)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23821 | L->catch_or_finally = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23822 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23823 | CALL_PARSE_IDENT(fid_p_try_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23824 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23825 | CALL_PARSE_BLOCK(fid_p_try_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23826 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23827 | ast_set_skip(a, L->start, AST_TRY_FINALLY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23828 | if (ACCEPT(TOK_FINALLY)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23829 | L->catch_or_finally = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23830 | CALL_PARSE_BLOCK(fid_p_try_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23831 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23832 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23834 | /* make sure `catch` and `finally` aren't both missing */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23835 | if (!L->catch_or_finally) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23836 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23837 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23839 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23840 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23842 | /* static enum v7_err parse_switch(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23843 | fid_parse_switch : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23844 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23845 | #define L CR_CUR_LOCALS_PT(fid_parse_switch_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23846 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23847 | L->start = add_node(v7, a, AST_SWITCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23848 | L->saved_in_switch = v7->pstate.in_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23850 | ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP); /* clear out */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23851 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23852 | CALL_PARSE_EXPRESSION(fid_p_switch_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23853 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23854 | EXPECT(TOK_OPEN_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23855 | v7->pstate.in_switch = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23856 | while (v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23857 | switch (v7->cur_tok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23858 | case TOK_CASE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23859 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23860 | L->case_start = add_node(v7, a, AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23861 | CALL_PARSE_EXPRESSION(fid_p_switch_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23862 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23863 | while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23864 | v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23865 | CALL_PARSE_STATEMENT(fid_p_switch_3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23867 | ast_set_skip(a, L->case_start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23868 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23869 | case TOK_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23870 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23871 | EXPECT(TOK_COLON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23872 | ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23873 | L->case_start = add_node(v7, a, AST_DEFAULT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23874 | while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT && |
Marko Mikulicic |
0:c0ecb8bf28eb | 23875 | v7->cur_tok != TOK_CLOSE_CURLY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23876 | CALL_PARSE_STATEMENT(fid_p_switch_4); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23878 | ast_set_skip(a, L->case_start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23879 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23880 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23881 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23882 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23883 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23884 | EXPECT(TOK_CLOSE_CURLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23885 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23886 | v7->pstate.in_switch = L->saved_in_switch; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23887 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23890 | /* static enum v7_err parse_with(struct v7 *v7, struct ast *a) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23891 | fid_parse_with : |
Marko Mikulicic |
0:c0ecb8bf28eb | 23892 | #undef L |
Marko Mikulicic |
0:c0ecb8bf28eb | 23893 | #define L CR_CUR_LOCALS_PT(fid_parse_with_locals_t) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23894 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23895 | L->start = add_node(v7, a, AST_WITH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23896 | if (v7->pstate.in_strict) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23897 | CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23898 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23899 | EXPECT(TOK_OPEN_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23900 | CALL_PARSE_EXPRESSION(fid_p_with_1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23901 | EXPECT(TOK_CLOSE_PAREN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23902 | CALL_PARSE_STATEMENT(fid_p_with_2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23903 | ast_set_skip(a, L->start, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23904 | CR_RETURN_VOID(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23907 | fid_none: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23908 | /* stack is empty, so we're done; return */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23909 | return rc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23912 | V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src, |
Marko Mikulicic |
0:c0ecb8bf28eb | 23913 | size_t src_len, int is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23914 | enum v7_err rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23915 | const char *error_msg = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23916 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23917 | struct cr_ctx cr_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23918 | union user_arg_ret arg_retval; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23919 | enum cr_status rc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23920 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23921 | struct stack_track_ctx stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23922 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23923 | int saved_line_no = v7->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23925 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23926 | v7_stack_track_start(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23927 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 23928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23929 | v7->pstate.source_code = v7->pstate.pc = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23930 | v7->pstate.src_end = src + src_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23931 | v7->pstate.file_name = "<stdin>"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23932 | v7->pstate.line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23933 | v7->pstate.in_function = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23934 | v7->pstate.in_loop = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23935 | v7->pstate.in_switch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23937 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23938 | * TODO(dfrank): `v7->parser.line_no` vs `v7->line_no` is confusing. probaby |
Marko Mikulicic |
0:c0ecb8bf28eb | 23939 | * we need to refactor it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23940 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 23941 | * See comment for v7->line_no in core.h for some details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23942 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23943 | v7->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23945 | next_tok(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23946 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 23947 | * setup initial state for "after newline" tracking. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23948 | * next_tok will consume our token and position the current line |
Marko Mikulicic |
0:c0ecb8bf28eb | 23949 | * position at the beginning of the next token. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23950 | * While processing the first token, both the leading and the |
Marko Mikulicic |
0:c0ecb8bf28eb | 23951 | * trailing newlines will be counted and thus it will create a spurious |
Marko Mikulicic |
0:c0ecb8bf28eb | 23952 | * "after newline" condition at the end of the first token |
Marko Mikulicic |
0:c0ecb8bf28eb | 23953 | * regardless if there is actually a newline after it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 23954 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23955 | for (p = src; isspace((int) *p); p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23956 | if (*p == '\n') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23957 | v7->pstate.prev_line_no++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23958 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23959 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23961 | /* init cr context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23962 | cr_context_init(&cr_ctx, &arg_retval, sizeof(arg_retval), _fid_descrs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23964 | /* prepare first function call: fid_mul_sum */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23965 | if (is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23966 | CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_terminal); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23967 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23968 | CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_script); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23971 | /* proceed to coroutine execution */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23972 | rc = parser_cr_exec(&cr_ctx, v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 23973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23974 | /* set `rcode` depending on coroutine state */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 23975 | switch (rc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23976 | case CR_RES__OK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23977 | rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23978 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23979 | case CR_RES__ERR_UNCAUGHT_EXCEPTION: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23980 | switch ((enum parser_exc_id) CR_THROWN_C(&cr_ctx)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 23981 | case PARSER_EXC_ID__SYNTAX_ERROR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23982 | rcode = V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23983 | error_msg = "Syntax error"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23984 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23985 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23986 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23987 | rcode = V7_INTERNAL_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23988 | error_msg = "Internal error: no exception id set"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23989 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23990 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23991 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23992 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 23993 | rcode = V7_INTERNAL_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23994 | error_msg = "Internal error: unexpected parser coroutine return code"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23995 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 23996 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 23997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 23998 | #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 23999 | /* remember how much stack space was consumed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24000 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24001 | if (v7->parser_stack_data_max_size < cr_ctx.stack_data.size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24002 | v7->parser_stack_data_max_size = cr_ctx.stack_data.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24003 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 24004 | printf("parser_stack_data_max_size=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24005 | (unsigned int) v7->parser_stack_data_max_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24006 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24007 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24008 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24009 | if (v7->parser_stack_ret_max_size < cr_ctx.stack_ret.size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24010 | v7->parser_stack_ret_max_size = cr_ctx.stack_ret.size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24011 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 24012 | printf("parser_stack_ret_max_size=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24013 | (unsigned int) v7->parser_stack_ret_max_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24014 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24015 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24017 | #if defined(CR_TRACK_MAX_STACK_LEN) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24018 | if (v7->parser_stack_data_max_len < cr_ctx.stack_data_max_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24019 | v7->parser_stack_data_max_len = cr_ctx.stack_data_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24020 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 24021 | printf("parser_stack_data_max_len=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24022 | (unsigned int) v7->parser_stack_data_max_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24023 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24024 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24026 | if (v7->parser_stack_ret_max_len < cr_ctx.stack_ret_max_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24027 | v7->parser_stack_ret_max_len = cr_ctx.stack_ret_max_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24028 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 24029 | printf("parser_stack_ret_max_len=%u\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24030 | (unsigned int) v7->parser_stack_ret_max_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24031 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24032 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24033 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24034 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24035 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24036 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24037 | /* free resources occupied by context (at least, "stack" arrays) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24038 | cr_context_free(&cr_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24039 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24040 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24041 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24042 | int diff = v7_stack_track_end(v7, &stack_track_ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24043 | if (diff > v7->stack_stat[V7_STACK_STAT_PARSER]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24044 | v7->stack_stat[V7_STACK_STAT_PARSER] = diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24045 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24046 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24047 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24048 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24049 | /* Check if AST was overflown */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24050 | if (a->has_overflow) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24051 | rcode = v7_throwf(v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24052 | "Script too large (try V7_LARGE_AST build option)"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24053 | V7_THROW(V7_AST_TOO_LARGE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24054 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24056 | if (rcode == V7_OK && v7->cur_tok != TOK_END_OF_INPUT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24057 | rcode = V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24058 | error_msg = "Syntax error"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24059 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24061 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24062 | unsigned long col = get_column(v7->pstate.source_code, v7->tok); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24063 | int line_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24065 | assert(error_msg != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24066 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24067 | for (p = v7->tok - col; p < v7->pstate.src_end && *p != '\0' && *p != '\n'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24068 | p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24069 | line_len++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24070 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24072 | /* fixup line number: line_no points to the beginning of the next token */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24073 | for (; p < v7->pstate.pc; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24074 | if (*p == '\n') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24075 | v7->pstate.line_no--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24076 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24079 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24080 | * We already have a proper `rcode`, that's why we discard returned value |
Marko Mikulicic |
0:c0ecb8bf28eb | 24081 | * of `v7_throwf()`, which is always `V7_EXEC_EXCEPTION`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24082 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24083 | * TODO(dfrank): probably get rid of distinct error types, and use just |
Marko Mikulicic |
0:c0ecb8bf28eb | 24084 | * `V7_JS_EXCEPTION`. However it would be good to have a way to get exact |
Marko Mikulicic |
0:c0ecb8bf28eb | 24085 | * error type, so probably error object should contain some property with |
Marko Mikulicic |
0:c0ecb8bf28eb | 24086 | * error code, but it would make exceptions even more expensive, etc, etc. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24087 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24088 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24089 | enum v7_err _tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24090 | _tmp = v7_throwf(v7, SYNTAX_ERROR, "%s at line %d col %lu:\n%.*s\n%*s^", |
Marko Mikulicic |
0:c0ecb8bf28eb | 24091 | error_msg, v7->pstate.line_no, col, line_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24092 | v7->tok - col, (int) col - 1, ""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24093 | (void) _tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24094 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24095 | V7_THROW(rcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24096 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24098 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24099 | v7->line_no = saved_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24100 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24101 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24103 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24104 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 24105 | #line 1 "v7/src/compiler.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24106 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24107 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24108 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 24109 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 24110 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24112 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24113 | /* Amalgamated: #include "v7/src/compiler.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24114 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24115 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24116 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24117 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24118 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24119 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24121 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24123 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24124 | * The bytecode compiler takes an AST as input and produces one or more |
Marko Mikulicic |
0:c0ecb8bf28eb | 24125 | * bcode structure as output. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24126 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24127 | * Each script or function body is compiled into it's own bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24128 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24129 | * Each bcode stream produces a new value on the stack, i.e. its overall |
Marko Mikulicic |
0:c0ecb8bf28eb | 24130 | * stack diagram is: `( -- a)` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24131 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24132 | * This value will be then popped by the function caller or by v7_exec in case |
Marko Mikulicic |
0:c0ecb8bf28eb | 24133 | * of scripts. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24134 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24135 | * In JS, the value of a script is the value of the last statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24136 | * A script with no statement has an `undefined` value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24137 | * Functions instead require an explicit return value, so this matters only |
Marko Mikulicic |
0:c0ecb8bf28eb | 24138 | * for `v7_exec` and JS `eval`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24139 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24140 | * Since an empty script has an undefined value, and each script has to |
Marko Mikulicic |
0:c0ecb8bf28eb | 24141 | * yield a value, the script/function prologue consists of a PUSH_UNDEFINED. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24142 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24143 | * Each statement will be compiled to push a value on the stack. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24144 | * When a statement begins evaluating, the current TOS is thus either |
Marko Mikulicic |
0:c0ecb8bf28eb | 24145 | * the value of the previous statement or `undefined` in case of the first |
Marko Mikulicic |
0:c0ecb8bf28eb | 24146 | * statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24147 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24148 | * Every statement of a given script/function body always evaluates at the same |
Marko Mikulicic |
0:c0ecb8bf28eb | 24149 | * stack depth. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24150 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24151 | * In order to achieve that, after a statement is compiled out, a SWAP_DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24152 | * opcode is emitted, that drops the value of the previous statement (or the |
Marko Mikulicic |
0:c0ecb8bf28eb | 24153 | * initial `undefined`). Dropping the value after the next statement is |
Marko Mikulicic |
0:c0ecb8bf28eb | 24154 | * evaluated and not before has allows us to correctly implement exception |
Marko Mikulicic |
0:c0ecb8bf28eb | 24155 | * behaviour and the break statement. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24156 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24157 | * Compound statements are constructs such as `if`/`while`/`for`/`try`. These |
Marko Mikulicic |
0:c0ecb8bf28eb | 24158 | * constructs contain a body consisting of a possibly empty statement list. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24159 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24160 | * Unlike normal statements, compound statements don't produce a value |
Marko Mikulicic |
0:c0ecb8bf28eb | 24161 | * themselves. Their value is either the value of their last executed statement |
Marko Mikulicic |
0:c0ecb8bf28eb | 24162 | * in their body, or the previous statement in case their body is empty or not |
Marko Mikulicic |
0:c0ecb8bf28eb | 24163 | * evaluated at all. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24164 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24165 | * An example is: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24166 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24167 | * [source,js] |
Marko Mikulicic |
0:c0ecb8bf28eb | 24168 | * ---- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24169 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24170 | * 42; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24171 | * someUnexistingVariable; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24172 | * } catch(e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24173 | * while(true) {} |
Marko Mikulicic |
0:c0ecb8bf28eb | 24174 | * if(true) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24175 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24176 | * if(false) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24177 | * 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24178 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24179 | * break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24180 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24181 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24182 | * ---- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24183 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24185 | static const enum ast_tag assign_ast_map[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24186 | AST_REM, AST_MUL, AST_DIV, AST_XOR, AST_ADD, AST_SUB, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24187 | AST_OR, AST_AND, AST_LSHIFT, AST_RSHIFT, AST_URSHIFT}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24189 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24190 | extern void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24191 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24192 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24193 | V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24194 | struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24195 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24196 | V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24197 | ast_off_t *ppos, struct bcode *bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24198 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24199 | V7_PRIVATE enum v7_err binary_op(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24200 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24201 | uint8_t op; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24202 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24203 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24204 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24205 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24206 | case AST_ADD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24207 | op = OP_ADD; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24208 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24209 | case AST_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24210 | op = OP_SUB; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24211 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24212 | case AST_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24213 | op = OP_REM; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24214 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24215 | case AST_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24216 | op = OP_MUL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24217 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24218 | case AST_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24219 | op = OP_DIV; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24220 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24221 | case AST_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24222 | op = OP_LSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24223 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24224 | case AST_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24225 | op = OP_RSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24226 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24227 | case AST_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24228 | op = OP_URSHIFT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24229 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24230 | case AST_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24231 | op = OP_OR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24232 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24233 | case AST_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24234 | op = OP_XOR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24235 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24236 | case AST_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24237 | op = OP_AND; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24238 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24239 | case AST_EQ_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24240 | op = OP_EQ_EQ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24241 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24242 | case AST_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24243 | op = OP_EQ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24244 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24245 | case AST_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24246 | op = OP_NE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24247 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24248 | case AST_NE_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24249 | op = OP_NE_NE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24250 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24251 | case AST_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24252 | op = OP_LT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24253 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24254 | case AST_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24255 | op = OP_LE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24256 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24257 | case AST_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24258 | op = OP_GT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24259 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24260 | case AST_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24261 | op = OP_GE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24262 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24263 | case AST_INSTANCEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24264 | op = OP_INSTANCEOF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24265 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24266 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24267 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown binary ast node"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24268 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24270 | bcode_op(bbuilder, op); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24271 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24272 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24273 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24275 | V7_PRIVATE enum v7_err compile_binary(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24276 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24277 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24278 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24279 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24280 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24281 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24283 | V7_TRY(binary_op(bbuilder, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24284 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24285 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24286 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24288 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24289 | * `pos` should be an offset of the byte right after a tag |
Marko Mikulicic |
0:c0ecb8bf28eb | 24290 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24291 | static lit_t string_lit(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24292 | ast_off_t pos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24293 | size_t i = 0, name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24294 | val_t v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24295 | struct mbuf *m = &bbuilder->lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24296 | char *name = ast_get_inlined_data(a, pos, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24298 | /* temp disabled because of short lits */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24299 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 24300 | for (i = 0; i < m->len / sizeof(val_t); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24301 | v = ((val_t *) m->buf)[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24302 | if (v7_is_string(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24303 | size_t l; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24304 | const char *s = v7_get_string(bbuilder->v7, &v, &l); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24305 | if (name_len == l && memcmp(name, s, name_len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24306 | lit_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24307 | memset(&res, 0, sizeof(res)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24308 | res.idx = i + bcode_max_inline_type_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24309 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24310 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24311 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24312 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24313 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 24314 | (void) i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24315 | (void) v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24316 | (void) m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24317 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24318 | return bcode_add_lit(bbuilder, v7_mk_string(bbuilder->v7, name, name_len, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24319 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24320 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24321 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 24322 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 24323 | static enum v7_err regexp_lit(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24324 | ast_off_t pos, lit_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24325 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24326 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24327 | char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24328 | char *name = ast_get_inlined_data(a, pos, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24329 | val_t tmp = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24330 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24332 | for (p = name + name_len - 1; *p != '/';) p--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24334 | V7_TRY(v7_mk_regexp(bbuilder->v7, name + 1, p - (name + 1), p + 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24335 | (name + name_len) - p - 1, &tmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24337 | *res = bcode_add_lit(bbuilder, tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24339 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24340 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24342 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24343 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24344 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 24345 | static void append_lineno_if_changed(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24346 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24347 | int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24348 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24349 | if (line_no != 0 && line_no != v7->line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24350 | v7->line_no = line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24351 | bcode_append_lineno(bbuilder, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24352 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24354 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 24355 | static void append_lineno_if_changed(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24356 | struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24357 | int line_no) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24358 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24359 | (void) bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24360 | (void) line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24361 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24362 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24363 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24364 | static enum ast_tag fetch_tag(struct v7 *v7, struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24365 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24366 | ast_off_t *ppos_after_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24367 | enum ast_tag ret = ast_fetch_tag(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24368 | int line_no = ast_get_line_no(a, *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24369 | append_lineno_if_changed(v7, bbuilder, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24370 | if (ppos_after_tag != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24371 | *ppos_after_tag = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24372 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24373 | ast_move_to_children(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24374 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24375 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24377 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24378 | * a++ and a-- need to ignore the updated value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24379 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24380 | * Call this before updating the lhs. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24381 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24382 | static void fixup_post_op(struct bcode_builder *bbuilder, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24383 | if (tag == AST_POSTINC || tag == AST_POSTDEC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24384 | bcode_op(bbuilder, OP_UNSTASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24385 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24386 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24388 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24389 | * evaluate rhs expression. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24390 | * ++a and a++ are equivalent to a+=1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 24391 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24392 | static enum v7_err eval_assign_rhs(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24393 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24394 | enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24395 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24396 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24398 | /* a++ and a-- need to preserve initial value. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24399 | if (tag == AST_POSTINC || tag == AST_POSTDEC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24400 | bcode_op(bbuilder, OP_STASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24401 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24402 | if (tag >= AST_PREINC && tag <= AST_POSTDEC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24403 | bcode_op(bbuilder, OP_PUSH_ONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24404 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24405 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24406 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24408 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24409 | case AST_PREINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24410 | case AST_POSTINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24411 | bcode_op(bbuilder, OP_ADD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24412 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24413 | case AST_PREDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24414 | case AST_POSTDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24415 | bcode_op(bbuilder, OP_SUB); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24416 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24417 | case AST_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24418 | /* no operation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24419 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24420 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24421 | binary_op(bbuilder, assign_ast_map[tag - AST_ASSIGN - 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24422 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24424 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24425 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24428 | static enum v7_err compile_assign(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24429 | ast_off_t *ppos, enum ast_tag tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24430 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24431 | enum ast_tag ntag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24432 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24433 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24434 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24436 | ntag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24438 | switch (ntag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24439 | case AST_IDENT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24440 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24441 | if (tag != AST_ASSIGN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24442 | bcode_op_lit(bbuilder, OP_GET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24443 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24445 | V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24446 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24448 | fixup_post_op(bbuilder, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24449 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24450 | case AST_MEMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24451 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24452 | switch (ntag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24453 | case AST_MEMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24454 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24455 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24456 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24457 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24458 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24459 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24460 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24461 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24462 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24463 | /* unreachable, compilers are dumb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24464 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24465 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24466 | if (tag != AST_ASSIGN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24467 | bcode_op(bbuilder, OP_2DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24468 | bcode_op(bbuilder, OP_GET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24469 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24470 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24471 | V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24472 | bcode_op(bbuilder, OP_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24474 | fixup_post_op(bbuilder, tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24475 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24476 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24477 | /* We end up here on expressions like `1 = 2;`, it's a ReferenceError */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24478 | rcode = v7_throwf(bbuilder->v7, REFERENCE_ERROR, "unexpected ast node"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24479 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24481 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24482 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24483 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24484 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24485 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24486 | * Walks through all declarations (`var` and `function`) in the current scope, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24487 | * and adds names of all of them to `bcode->ops`. Additionally, `function` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24488 | * declarations are compiled right here, since they're hoisted in JS. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24489 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24490 | static enum v7_err compile_local_vars(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24491 | struct ast *a, ast_off_t start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24492 | ast_off_t fvar) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24493 | ast_off_t next, fvar_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24494 | char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24495 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24496 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24497 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24498 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24499 | size_t names_end = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24500 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24502 | /* calculate `names_end`: offset at which names in `bcode->ops` end */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24503 | names_end = |
Marko Mikulicic |
0:c0ecb8bf28eb | 24504 | (size_t)(bcode_end_names(bbuilder->ops.buf, bbuilder->bcode->names_cnt) - |
Marko Mikulicic |
0:c0ecb8bf28eb | 24505 | bbuilder->ops.buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24507 | if (fvar != start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24508 | /* iterate all `AST_VAR`s in the current scope */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24509 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24510 | V7_CHECK_INTERNAL(fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 24511 | AST_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24512 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24513 | next = ast_get_skip(a, pos_after_tag, AST_VAR_NEXT_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24514 | if (next == pos_after_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24515 | next = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24516 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24518 | fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24519 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24520 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24521 | * iterate all `AST_VAR_DECL`s and `AST_FUNC_DECL`s in the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 24522 | * `AST_VAR` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24523 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24524 | while (fvar < fvar_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24525 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24526 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL || tag == AST_FUNC_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24527 | name = ast_get_inlined_data(a, pos_after_tag, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24528 | if (tag == AST_VAR_DECL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24529 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24530 | * it's a `var` declaration, so, skip the value for now, it'll be set |
Marko Mikulicic |
0:c0ecb8bf28eb | 24531 | * to `undefined` initially |
Marko Mikulicic |
0:c0ecb8bf28eb | 24532 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24533 | ast_skip_tree(a, &fvar); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24534 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24535 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24536 | * tag is an AST_FUNC_DECL: since functions in JS are hoisted, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24537 | * we compile it and put `OP_SET_VAR` directly here |
Marko Mikulicic |
0:c0ecb8bf28eb | 24538 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24539 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24540 | V7_TRY(compile_expr_builder(bbuilder, a, &fvar)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24541 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24542 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24543 | /* function declarations are stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24544 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24545 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24546 | * Note: the `is_stack_neutral` flag will be set by `compile_stmt` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24547 | * later, when it encounters `AST_FUNC_DECL` again. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24548 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24549 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24550 | V7_TRY(bcode_add_name(bbuilder, name, name_len, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24551 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24552 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24553 | if (next > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24554 | fvar = next - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24555 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24557 | } while (next != 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24558 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24560 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24561 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24562 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24563 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24564 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24565 | * Just like `compile_expr_builder`, but it takes additional argument: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24566 | *`for_call`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24567 | * If it's non-zero, the stack is additionally populated with `this` value |
Marko Mikulicic |
0:c0ecb8bf28eb | 24568 | * for call. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24569 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24570 | * If there is a refinement (a dot, or a subscript), then it'll be the |
Marko Mikulicic |
0:c0ecb8bf28eb | 24571 | * appropriate object. Otherwise, it's `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24572 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24573 | * In non-strict mode, `undefined` will be changed to Global Object at runtime, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24574 | * see `OP_CALL` handling in `eval_bcode()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24575 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24576 | V7_PRIVATE enum v7_err compile_expr_ext(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24577 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24578 | uint8_t for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24579 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24580 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24581 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24582 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24584 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24585 | case AST_MEMBER: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24586 | lit_t lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24587 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24588 | if (for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24589 | /* current TOS will be used as `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24590 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24591 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24592 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24593 | bcode_op(bbuilder, OP_GET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24594 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24596 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24597 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24598 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24599 | if (for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24600 | /* current TOS will be used as `this` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24601 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24602 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24603 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24604 | bcode_op(bbuilder, OP_GET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24605 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24606 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24607 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24608 | if (for_call) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24609 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24610 | * `this` will be an `undefined` (but it may change to Global Object |
Marko Mikulicic |
0:c0ecb8bf28eb | 24611 | * at runtime) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24612 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24613 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24614 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24615 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24616 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24617 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24618 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24619 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24620 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24621 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24622 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24624 | V7_PRIVATE enum v7_err compile_delete(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24625 | struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24626 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24627 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24628 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24629 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24630 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24631 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24632 | case AST_MEMBER: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24633 | /* Delete a specified property of an object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24634 | lit_t lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24635 | /* put an object to delete property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24636 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24637 | /* put a property name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24638 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24639 | bcode_op(bbuilder, OP_DELETE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24640 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24643 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24644 | /* Delete a specified property of an object */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24645 | /* put an object to delete property from */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24646 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24647 | /* put a property name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24648 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24649 | bcode_op(bbuilder, OP_DELETE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24650 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24652 | case AST_IDENT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24653 | /* Delete the scope variable (or throw an error if strict mode) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24654 | if (!bbuilder->bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24655 | /* put a property name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24656 | bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24657 | bcode_op(bbuilder, OP_DELETE_VAR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24658 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24659 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 24660 | v7_throwf(bbuilder->v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24661 | "Delete of an unqualified identifier in strict mode."); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24662 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24663 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24664 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24666 | case AST_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24667 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24668 | * `undefined` should actually be an undeletable property of the Global |
Marko Mikulicic |
0:c0ecb8bf28eb | 24669 | * Object, so, trying to delete it just yields `false` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24670 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24671 | bcode_op(bbuilder, OP_PUSH_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24672 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24674 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24675 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24676 | * For all other cases, we evaluate the expression given to `delete` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24677 | * for side effects, then drop the result, and yield `true` |
Marko Mikulicic |
0:c0ecb8bf28eb | 24678 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24679 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24680 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24681 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24682 | bcode_op(bbuilder, OP_PUSH_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24683 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24686 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24687 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24688 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24690 | V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24691 | struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24692 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24693 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24694 | ast_off_t pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24695 | enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24697 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24698 | case AST_ADD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24699 | case AST_SUB: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24700 | case AST_REM: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24701 | case AST_MUL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24702 | case AST_DIV: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24703 | case AST_LSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24704 | case AST_RSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24705 | case AST_URSHIFT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24706 | case AST_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24707 | case AST_XOR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24708 | case AST_AND: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24709 | case AST_EQ_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24710 | case AST_EQ: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24711 | case AST_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24712 | case AST_NE_NE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24713 | case AST_LT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24714 | case AST_LE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24715 | case AST_GT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24716 | case AST_GE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24717 | case AST_INSTANCEOF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24718 | V7_TRY(compile_binary(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24719 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24720 | case AST_LOGICAL_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24721 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24722 | bcode_op(bbuilder, OP_LOGICAL_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24723 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24724 | case AST_NOT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24725 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24726 | bcode_op(bbuilder, OP_NOT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24727 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24728 | case AST_POSITIVE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24729 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24730 | bcode_op(bbuilder, OP_POS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24731 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24732 | case AST_NEGATIVE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24733 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24734 | bcode_op(bbuilder, OP_NEG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24735 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24736 | case AST_IDENT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24737 | bcode_op_lit(bbuilder, OP_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24738 | string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24739 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24740 | case AST_MEMBER: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24741 | case AST_INDEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24742 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24743 | * These two are handled by the "extended" version of this function, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24744 | * since we may need to put `this` value on stack, for "method pattern |
Marko Mikulicic |
0:c0ecb8bf28eb | 24745 | * invocation". |
Marko Mikulicic |
0:c0ecb8bf28eb | 24746 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24747 | * First of all, restore starting AST position, and then call extended |
Marko Mikulicic |
0:c0ecb8bf28eb | 24748 | * function. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24749 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24750 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24751 | V7_TRY(compile_expr_ext(bbuilder, a, ppos, 0 /*not for call*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24752 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24753 | case AST_IN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24754 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24755 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24756 | bcode_op(bbuilder, OP_IN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24757 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24758 | case AST_TYPEOF: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24759 | ast_off_t lookahead = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24760 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24761 | if (tag == AST_IDENT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24762 | *ppos = lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24763 | bcode_op_lit(bbuilder, OP_SAFE_GET_VAR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24764 | string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24765 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24766 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24767 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24768 | bcode_op(bbuilder, OP_TYPEOF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24769 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24770 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24771 | case AST_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24772 | case AST_PREINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24773 | case AST_PREDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24774 | case AST_POSTINC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24775 | case AST_POSTDEC: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24776 | case AST_REM_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24777 | case AST_MUL_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24778 | case AST_DIV_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24779 | case AST_XOR_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24780 | case AST_PLUS_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24781 | case AST_MINUS_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24782 | case AST_OR_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24783 | case AST_AND_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24784 | case AST_LSHIFT_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24785 | case AST_RSHIFT_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24786 | case AST_URSHIFT_ASSIGN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24787 | V7_TRY(compile_assign(bbuilder, a, ppos, tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24788 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24789 | case AST_COND: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24790 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24791 | * A ? B : C |
Marko Mikulicic |
0:c0ecb8bf28eb | 24792 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24793 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24794 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24795 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24796 | * JMP_FALSE false |
Marko Mikulicic |
0:c0ecb8bf28eb | 24797 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24798 | * JMP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 24799 | * false: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24800 | * <C> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24801 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24802 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24803 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24804 | bcode_off_t false_label, end_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24805 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24806 | false_label = bcode_op_target(bbuilder, OP_JMP_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24807 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24808 | end_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24809 | bcode_patch_target(bbuilder, false_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24810 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24811 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24812 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24813 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24814 | case AST_LOGICAL_OR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24815 | case AST_LOGICAL_AND: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24816 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24817 | * A && B |
Marko Mikulicic |
0:c0ecb8bf28eb | 24818 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24819 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24820 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24821 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24822 | * JMP_FALSE end |
Marko Mikulicic |
0:c0ecb8bf28eb | 24823 | * POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24824 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24825 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24826 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24827 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24828 | bcode_off_t end_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24829 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24830 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24831 | end_label = bcode_op_target( |
Marko Mikulicic |
0:c0ecb8bf28eb | 24832 | bbuilder, tag == AST_LOGICAL_AND ? OP_JMP_FALSE : OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24833 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24834 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24835 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24836 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24837 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24838 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24839 | * A, B, C |
Marko Mikulicic |
0:c0ecb8bf28eb | 24840 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24841 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24842 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24843 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24844 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24845 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24846 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24847 | * <C> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24848 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24849 | case AST_SEQ: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24850 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24851 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24852 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24853 | if (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24854 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24855 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24856 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24857 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24858 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24859 | case AST_CALL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24860 | case AST_NEW: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24861 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24862 | * f() |
Marko Mikulicic |
0:c0ecb8bf28eb | 24863 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24864 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24865 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24866 | * PUSH_UNDEFINED (value for `this`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24867 | * GET_VAR "f" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24868 | * CHECK_CALL |
Marko Mikulicic |
0:c0ecb8bf28eb | 24869 | * CALL 0 args |
Marko Mikulicic |
0:c0ecb8bf28eb | 24870 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24871 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24872 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24873 | * f(a, b) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24874 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24875 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24876 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24877 | * PUSH_UNDEFINED (value for `this`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24878 | * GET_VAR "f" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24879 | * CHECK_CALL |
Marko Mikulicic |
0:c0ecb8bf28eb | 24880 | * GET_VAR "a" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24881 | * GET_VAR "b" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24882 | * CALL 2 args |
Marko Mikulicic |
0:c0ecb8bf28eb | 24883 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24884 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 24885 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24886 | * o.f(a, b) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24887 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24888 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24889 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24890 | * GET_VAR "o" (so that `this` will be an `o`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24891 | * DUP (we'll also need `o` for GET below, so, duplicate it) |
Marko Mikulicic |
0:c0ecb8bf28eb | 24892 | * PUSH_LIT "f" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24893 | * GET (get property "f" of the object "o") |
Marko Mikulicic |
0:c0ecb8bf28eb | 24894 | * CHECK_CALL |
Marko Mikulicic |
0:c0ecb8bf28eb | 24895 | * GET_VAR "a" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24896 | * GET_VAR "b" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24897 | * CALL 2 args |
Marko Mikulicic |
0:c0ecb8bf28eb | 24898 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24899 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24900 | int args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24901 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24902 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24903 | V7_TRY(compile_expr_ext(bbuilder, a, ppos, 1 /*for call*/)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24904 | bcode_op(bbuilder, OP_CHECK_CALL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24905 | for (args = 0; *ppos < end; args++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24906 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24907 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24908 | bcode_op(bbuilder, (tag == AST_CALL ? OP_CALL : OP_NEW)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24909 | if (args > 0x7f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24910 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "too many arguments"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24911 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24912 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24913 | bcode_op(bbuilder, (uint8_t) args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24914 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24916 | case AST_DELETE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24917 | V7_TRY(compile_delete(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24918 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24920 | case AST_OBJECT: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24921 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24922 | * {a:<B>, ...} |
Marko Mikulicic |
0:c0ecb8bf28eb | 24923 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24924 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24925 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 24926 | * CREATE_OBJ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24927 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24928 | * PUSH_LIT "a" |
Marko Mikulicic |
0:c0ecb8bf28eb | 24929 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 24930 | * SET |
Marko Mikulicic |
0:c0ecb8bf28eb | 24931 | * POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 24932 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 24933 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24935 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24936 | * Literal indices of property names of current object literal. |
Marko Mikulicic |
0:c0ecb8bf28eb | 24937 | * Needed for strict mode: we need to keep track of the added |
Marko Mikulicic |
0:c0ecb8bf28eb | 24938 | * properties, since duplicates are not allowed |
Marko Mikulicic |
0:c0ecb8bf28eb | 24939 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24940 | struct mbuf cur_literals; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24941 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24942 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24943 | mbuf_init(&cur_literals, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24945 | bcode_op(bbuilder, OP_CREATE_OBJ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24946 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24947 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24948 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24949 | case AST_PROP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24950 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24951 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24953 | /* disabled because we broke get_lit */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24954 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 24955 | if (bbuilder->bcode->strict_mode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24956 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 24957 | * In strict mode, check for duplicate property names in |
Marko Mikulicic |
0:c0ecb8bf28eb | 24958 | * object literals |
Marko Mikulicic |
0:c0ecb8bf28eb | 24959 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24960 | char *plit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24961 | for (plit = (char *) cur_literals.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24962 | (char *) plit < cur_literals.buf + cur_literals.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24963 | plit++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24964 | const char *str1, *str2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24965 | size_t size1, size2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24966 | v7_val_t val1, val2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24968 | val1 = bcode_get_lit(bbuilder->bcode, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24969 | str1 = v7_get_string(bbuilder->v7, &val1, &size1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24971 | val2 = bcode_get_lit(bbuilder->bcode, *plit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24972 | str2 = v7_get_string(bbuilder->v7, &val2, &size2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24973 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24974 | if (size1 == size2 && memcmp(str1, str2, size1) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24975 | /* found already existing property of the same name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 24976 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 24977 | "duplicate data property in object literal " |
Marko Mikulicic |
0:c0ecb8bf28eb | 24978 | "is not allowed in strict mode"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24979 | V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24980 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24982 | mbuf_append(&cur_literals, &lit, sizeof(lit)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24983 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24984 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 24985 | bcode_push_lit(bbuilder, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24986 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24987 | bcode_op(bbuilder, OP_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24988 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24989 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 24990 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24991 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24992 | V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24993 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24994 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 24995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 24996 | ast_object_clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 24997 | mbuf_free(&cur_literals); |
Marko Mikulicic |
0:c0ecb8bf28eb | 24998 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 24999 | V7_THROW(rcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25001 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25002 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25003 | case AST_ARRAY: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25004 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25005 | * [<A>,,<B>,...] |
Marko Mikulicic |
0:c0ecb8bf28eb | 25006 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25007 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25008 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25009 | * CREATE_ARR |
Marko Mikulicic |
0:c0ecb8bf28eb | 25010 | * PUSH_ZERO |
Marko Mikulicic |
0:c0ecb8bf28eb | 25011 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25012 | * 2DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25013 | * <A> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25014 | * SET |
Marko Mikulicic |
0:c0ecb8bf28eb | 25015 | * POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25016 | * PUSH_ONE |
Marko Mikulicic |
0:c0ecb8bf28eb | 25017 | * ADD |
Marko Mikulicic |
0:c0ecb8bf28eb | 25018 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25019 | * PUSH_ONE |
Marko Mikulicic |
0:c0ecb8bf28eb | 25020 | * ADD |
Marko Mikulicic |
0:c0ecb8bf28eb | 25021 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25022 | * 2DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25023 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25024 | * ... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25025 | * POP // tmp index |
Marko Mikulicic |
0:c0ecb8bf28eb | 25026 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25027 | * TODO(mkm): optimize this out. we can have more compact array push |
Marko Mikulicic |
0:c0ecb8bf28eb | 25028 | * that uses a special marker value for missing array elements |
Marko Mikulicic |
0:c0ecb8bf28eb | 25029 | * (which are not the same as undefined btw) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25030 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25031 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25032 | bcode_op(bbuilder, OP_CREATE_ARR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25033 | bcode_op(bbuilder, OP_PUSH_ZERO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25034 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25035 | ast_off_t lookahead = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25036 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25037 | if (tag != AST_NOP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25038 | bcode_op(bbuilder, OP_2DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25039 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25040 | bcode_op(bbuilder, OP_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25041 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25042 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25043 | *ppos = lookahead; /* skip nop */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25044 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25045 | bcode_op(bbuilder, OP_PUSH_ONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25046 | bcode_op(bbuilder, OP_ADD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25047 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25048 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25049 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25050 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25051 | case AST_FUNC: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25052 | lit_t flit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25054 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25055 | * Create half-done function: without scope and prototype. The real |
Marko Mikulicic |
0:c0ecb8bf28eb | 25056 | * function will be created from this one during bcode evaluation: see |
Marko Mikulicic |
0:c0ecb8bf28eb | 25057 | * `bcode_instantiate_function()`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25058 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25059 | val_t funv = mk_js_function(bbuilder->v7, NULL, V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25061 | /* Create bcode in this half-done function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25062 | struct v7_js_function *func = get_js_function_struct(funv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25063 | func->bcode = (struct bcode *) calloc(1, sizeof(*bbuilder->bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25064 | bcode_init(func->bcode, bbuilder->bcode->strict_mode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25065 | NULL /* will be set below */, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25066 | bcode_copy_filename_from(func->bcode, bbuilder->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25067 | retain_bcode(bbuilder->v7, func->bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25068 | flit = bcode_add_lit(bbuilder, funv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25070 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25071 | V7_TRY(compile_function(v7, a, ppos, func->bcode)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25072 | bcode_push_lit(bbuilder, flit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25073 | bcode_op(bbuilder, OP_FUNC_LIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25074 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25075 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25076 | case AST_THIS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25077 | bcode_op(bbuilder, OP_PUSH_THIS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25078 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25079 | case AST_VOID: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25080 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25081 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25082 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25083 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25084 | case AST_NULL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25085 | bcode_op(bbuilder, OP_PUSH_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25086 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25087 | case AST_NOP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25088 | case AST_UNDEFINED: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25089 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25090 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25091 | case AST_TRUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25092 | bcode_op(bbuilder, OP_PUSH_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25093 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25094 | case AST_FALSE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25095 | bcode_op(bbuilder, OP_PUSH_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25096 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25097 | case AST_NUM: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25098 | double dv = ast_get_num(a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25099 | if (dv == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25100 | bcode_op(bbuilder, OP_PUSH_ZERO); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25101 | } else if (dv == 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25102 | bcode_op(bbuilder, OP_PUSH_ONE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25103 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25104 | bcode_push_lit(bbuilder, bcode_add_lit(bbuilder, v7_mk_number(v7, dv))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25105 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25106 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25107 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25108 | case AST_STRING: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25109 | bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25110 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25111 | case AST_REGEX: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25112 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 25113 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25114 | lit_t tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25115 | rcode = regexp_lit(bbuilder, a, pos_after_tag, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25116 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25117 | rcode = V7_SYNTAX_ERROR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25118 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25119 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25121 | bcode_push_lit(bbuilder, tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25122 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25123 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25124 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 25125 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 25126 | v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Regexp support is disabled"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25127 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25128 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 25129 | case AST_LABEL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25130 | case AST_LABELED_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25131 | case AST_LABELED_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25132 | /* TODO(dfrank): implement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25133 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25134 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25135 | case AST_WITH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25136 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25137 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25138 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25139 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25140 | * We end up here if the AST is broken. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25141 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25142 | * It might be appropriate to return `V7_INTERNAL_ERROR` here, but since |
Marko Mikulicic |
0:c0ecb8bf28eb | 25143 | * we might receive AST from network or something, we just interpret |
Marko Mikulicic |
0:c0ecb8bf28eb | 25144 | * it as SyntaxError. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25145 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25146 | rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown ast node %d", |
Marko Mikulicic |
0:c0ecb8bf28eb | 25147 | (int) tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25148 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25149 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25150 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25151 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25152 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25154 | V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25155 | struct ast *a, ast_off_t *ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25157 | V7_PRIVATE enum v7_err compile_stmts(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25158 | struct ast *a, ast_off_t *ppos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25159 | ast_off_t end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25160 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25161 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25162 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25163 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25164 | V7_TRY(compile_stmt(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25165 | if (!bbuilder->v7->is_stack_neutral) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25166 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25167 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25168 | bbuilder->v7->is_stack_neutral = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25169 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25170 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25171 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25172 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25175 | V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25176 | struct ast *a, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25177 | ast_off_t end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25178 | enum ast_tag tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25179 | ast_off_t cond, pos_after_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25180 | bcode_off_t body_target, body_label, cond_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25181 | struct mbuf case_labels; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25182 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25183 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25185 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25187 | mbuf_init(&case_labels, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25188 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25189 | switch (tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25190 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25191 | * if(E) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25192 | * BT... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25193 | * } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25194 | * BF... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25195 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25196 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25197 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25198 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25199 | * <E> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25200 | * JMP_FALSE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25201 | * <BT> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25202 | * JMP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25203 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25204 | * <BF> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25205 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25206 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25207 | * If else clause is omitted, it will emit output equivalent to: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25208 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25209 | * if(E) {BT} else undefined; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25210 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25211 | case AST_IF: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25212 | ast_off_t if_false; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25213 | bcode_off_t end_label, if_false_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25214 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25215 | if_false = ast_get_skip(a, pos_after_tag, AST_END_IF_TRUE_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25216 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25217 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25218 | if_false_label = bcode_op_target(bbuilder, OP_JMP_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25220 | /* body if true */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25221 | V7_TRY(compile_stmts(bbuilder, a, ppos, if_false)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25222 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25223 | if (if_false != end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25224 | /* `else` branch is present */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25225 | end_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25226 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25227 | /* will jump here if `false` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25228 | bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25229 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25230 | /* body if false */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25231 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25232 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25233 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25234 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25235 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25236 | * `else` branch is not present: just remember where we should |
Marko Mikulicic |
0:c0ecb8bf28eb | 25237 | * jump in case of `false` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25238 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25239 | bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25240 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25242 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25243 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25244 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25245 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25246 | * while(C) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25247 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25248 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25249 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25250 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25251 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25252 | * TRY_PUSH_LOOP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25253 | * JMP cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25254 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25255 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25256 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25257 | * <C> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25258 | * JMP_TRUE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25259 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25260 | * JMP_IF_CONTINUE cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25261 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25262 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25263 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25264 | case AST_WHILE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25265 | bcode_off_t end_label, continue_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25266 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25267 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25268 | cond = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25269 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25271 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25272 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25273 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25274 | * Condition check is at the end of the loop, this layout |
Marko Mikulicic |
0:c0ecb8bf28eb | 25275 | * reduces the number of jumps in the steady state. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25276 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25277 | cond_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25278 | body_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25279 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25280 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25282 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25283 | bcode_patch_target(bbuilder, cond_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25284 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25285 | V7_TRY(compile_expr_builder(bbuilder, a, &cond)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25286 | body_label = bcode_op_target(bbuilder, OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25287 | bcode_patch_target(bbuilder, body_label, body_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25289 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25290 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25291 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25292 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25293 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25294 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25295 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25296 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25297 | case AST_BREAK: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25298 | bcode_op(bbuilder, OP_BREAK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25299 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25300 | case AST_CONTINUE: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25301 | bcode_op(bbuilder, OP_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25302 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25303 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25304 | * Frame objects (`v7->vals.call_stack`) contain one more hidden property: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25305 | * `____t`, which is an array of offsets in bcode. Each element of the array |
Marko Mikulicic |
0:c0ecb8bf28eb | 25306 | * is an offset of either `catch` or `finally` block (distinguished by the |
Marko Mikulicic |
0:c0ecb8bf28eb | 25307 | * tag: `OFFSET_TAG_CATCH` or `OFFSET_TAG_FINALLY`). Let's call this array |
Marko Mikulicic |
0:c0ecb8bf28eb | 25308 | * as a "try stack". When evaluator enters new `try` block, it adds |
Marko Mikulicic |
0:c0ecb8bf28eb | 25309 | * appropriate offset(s) at the top of "try stack", and when we unwind the |
Marko Mikulicic |
0:c0ecb8bf28eb | 25310 | * stack, we can "pop" offsets from "try stack" at each level. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25311 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25312 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25313 | * TRY_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25314 | * } catch (e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25315 | * CATCH_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25316 | * } finally { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25317 | * FIN_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25318 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25319 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25320 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25321 | * OP_TRY_PUSH_FINALLY finally |
Marko Mikulicic |
0:c0ecb8bf28eb | 25322 | * OP_TRY_PUSH_CATCH catch |
Marko Mikulicic |
0:c0ecb8bf28eb | 25323 | * <TRY_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25324 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25325 | * JMP finally |
Marko Mikulicic |
0:c0ecb8bf28eb | 25326 | * catch: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25327 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25328 | * OP_ENTER_CATCH <e> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25329 | * <CATCH_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25330 | * OP_EXIT_CATCH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25331 | * finally: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25332 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25333 | * <FIN_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25334 | * OP_AFTER_FINALLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 25335 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25336 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 25337 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25338 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25339 | * TRY_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25340 | * } catch (e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25341 | * CATCH_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25342 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25343 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25344 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25345 | * OP_TRY_PUSH_CATCH catch |
Marko Mikulicic |
0:c0ecb8bf28eb | 25346 | * <TRY_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25347 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25348 | * JMP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25349 | * catch: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25350 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25351 | * OP_ENTER_CATCH <e> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25352 | * <CATCH_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25353 | * OP_EXIT_CATCH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25354 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25355 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25356 | * --------------- |
Marko Mikulicic |
0:c0ecb8bf28eb | 25357 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25358 | * try { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25359 | * TRY_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25360 | * } finally { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25361 | * FIN_B |
Marko Mikulicic |
0:c0ecb8bf28eb | 25362 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25363 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25364 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25365 | * OP_TRY_PUSH_FINALLY finally |
Marko Mikulicic |
0:c0ecb8bf28eb | 25366 | * <TRY_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25367 | * finally: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25368 | * OP_TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25369 | * <FIN_B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25370 | * OP_AFTER_FINALLY |
Marko Mikulicic |
0:c0ecb8bf28eb | 25371 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25372 | case AST_TRY: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25373 | ast_off_t acatch, afinally; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25374 | bcode_off_t finally_label, catch_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25376 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25377 | acatch = ast_get_skip(a, pos_after_tag, AST_TRY_CATCH_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25378 | afinally = ast_get_skip(a, pos_after_tag, AST_TRY_FINALLY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25380 | if (afinally != end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25381 | /* `finally` clause is present: push its offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25382 | finally_label = bcode_op_target(bbuilder, OP_TRY_PUSH_FINALLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25383 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25385 | if (acatch != afinally) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25386 | /* `catch` clause is present: push its offset */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25387 | catch_label = bcode_op_target(bbuilder, OP_TRY_PUSH_CATCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25390 | /* compile statements of `try` block */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25391 | V7_TRY(compile_stmts(bbuilder, a, ppos, acatch)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25393 | if (acatch != afinally) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25394 | /* `catch` clause is present: compile it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25395 | bcode_off_t after_catch_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25397 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25398 | * pop offset pushed by OP_TRY_PUSH_CATCH, and jump over the `catch` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25399 | * block |
Marko Mikulicic |
0:c0ecb8bf28eb | 25400 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25401 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25402 | after_catch_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25403 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25404 | /* --- catch --- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25405 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25406 | /* in case of exception in the `try` block above, we'll get here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25407 | bcode_patch_target(bbuilder, catch_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25409 | /* pop offset pushed by OP_TRY_PUSH_CATCH */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25410 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25412 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25413 | * retrieve identifier where to store thrown error, and make sure |
Marko Mikulicic |
0:c0ecb8bf28eb | 25414 | * it is actually an indentifier (AST_IDENT) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25415 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25416 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25417 | V7_CHECK(tag == AST_IDENT, V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25419 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25420 | * when we enter `catch` block, the TOS contains thrown value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25421 | * We should create private frame for the `catch` clause, and populate |
Marko Mikulicic |
0:c0ecb8bf28eb | 25422 | * a variable with the thrown value there. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25423 | * The `OP_ENTER_CATCH` opcode does just that. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25424 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25425 | bcode_op_lit(bbuilder, OP_ENTER_CATCH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25426 | string_lit(bbuilder, a, pos_after_tag)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25428 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25429 | * compile statements until the end of `catch` clause |
Marko Mikulicic |
0:c0ecb8bf28eb | 25430 | * (`afinally` points to the end of the `catch` clause independently |
Marko Mikulicic |
0:c0ecb8bf28eb | 25431 | * of whether the `finally` clause is present) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25432 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25433 | V7_TRY(compile_stmts(bbuilder, a, ppos, afinally)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25434 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25435 | /* pop private frame */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25436 | bcode_op(bbuilder, OP_EXIT_CATCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25438 | bcode_patch_target(bbuilder, after_catch_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25439 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25441 | if (afinally != end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25442 | /* `finally` clause is present: compile it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25443 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25444 | /* --- finally --- */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25445 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25446 | /* after the `try` block above executes, we'll get here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25447 | bcode_patch_target(bbuilder, finally_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25449 | /* pop offset pushed by OP_TRY_PUSH_FINALLY */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25450 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25451 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25452 | /* compile statements until the end of `finally` clause */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25453 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25455 | bcode_op(bbuilder, OP_AFTER_FINALLY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25456 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25457 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25458 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25459 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25462 | case AST_THROW: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25463 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25464 | bcode_op(bbuilder, OP_THROW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25465 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25466 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25467 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25468 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25469 | * switch(E) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25470 | * default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25471 | * D... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25472 | * case C1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25473 | * B1... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25474 | * case C2: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25475 | * B2... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25476 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25477 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25478 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25479 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25480 | * TRY_PUSH_SWITCH end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25481 | * <E> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25482 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25483 | * <C1> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25484 | * EQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25485 | * JMP_TRUE_DROP l1 |
Marko Mikulicic |
0:c0ecb8bf28eb | 25486 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25487 | * <C2> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25488 | * EQ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25489 | * JMP_TRUE_DROP l2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 25490 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25491 | * JMP dfl |
Marko Mikulicic |
0:c0ecb8bf28eb | 25492 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25493 | * dfl: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25494 | * <D> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25495 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25496 | * l1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25497 | * <B1> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25498 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25499 | * l2: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25500 | * <B2> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25501 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25502 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25503 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25504 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25505 | * If the default case is missing we treat it as if had an empty body and |
Marko Mikulicic |
0:c0ecb8bf28eb | 25506 | * placed in last position (i.e. `dfl` label is replaced with `end`). |
Marko Mikulicic |
0:c0ecb8bf28eb | 25507 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25508 | * Before emitting a case/default block (except the first one) we have to |
Marko Mikulicic |
0:c0ecb8bf28eb | 25509 | * drop the TOS resulting from evaluating the last expression |
Marko Mikulicic |
0:c0ecb8bf28eb | 25510 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25511 | case AST_SWITCH: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25512 | bcode_off_t dfl_label, end_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25513 | ast_off_t case_end, case_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25514 | enum ast_tag case_tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25515 | int i, has_default = 0, cases = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25517 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25519 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_SWITCH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25521 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25522 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25523 | case_start = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25524 | /* first pass: evaluate case expression and generate jump table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25525 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25526 | case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25527 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25529 | case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25531 | switch (case_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25532 | case AST_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25533 | /* default jump table entry must be the last one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25534 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25535 | case AST_CASE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25536 | bcode_off_t case_label; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25537 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25538 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25539 | bcode_op(bbuilder, OP_EQ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25540 | case_label = bcode_op_target(bbuilder, OP_JMP_TRUE_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25541 | cases++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25542 | mbuf_append(&case_labels, &case_label, sizeof(case_label)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25543 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25544 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25545 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25546 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25547 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25548 | *ppos = case_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25549 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25550 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25551 | /* jmp table epilogue: unconditional jump to default case */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25552 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25553 | dfl_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25555 | *ppos = case_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25556 | /* second pass: emit case bodies and patch jump table */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25557 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25558 | for (i = 0; *ppos < end;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25559 | case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25560 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25561 | assert(i <= cases); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25562 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25563 | case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25565 | switch (case_tag) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25566 | case AST_DEFAULT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25567 | has_default = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25568 | bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25569 | V7_TRY(compile_stmts(bbuilder, a, ppos, case_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25570 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25571 | case AST_CASE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25572 | bcode_off_t case_label = ((bcode_off_t *) case_labels.buf)[i++]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25573 | bcode_patch_target(bbuilder, case_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25574 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25575 | V7_TRY(compile_stmts(bbuilder, a, ppos, case_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25576 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25577 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25578 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25579 | assert(case_tag == AST_DEFAULT || case_tag == AST_CASE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25580 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25582 | *ppos = case_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25583 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25584 | mbuf_free(&case_labels); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25586 | if (!has_default) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25587 | bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25588 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25589 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25590 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25591 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25593 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25594 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25596 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25597 | * for(INIT,COND,IT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25598 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25599 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25600 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25601 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25602 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25603 | * <INIT> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25604 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25605 | * TRY_PUSH_LOOP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25606 | * JMP cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25607 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25608 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25609 | * next: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25610 | * <IT> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25611 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25612 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25613 | * <COND> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25614 | * JMP_TRUE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25615 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25616 | * JMP_IF_CONTINUE next |
Marko Mikulicic |
0:c0ecb8bf28eb | 25617 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25618 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25619 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25620 | case AST_FOR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25621 | ast_off_t iter, body, lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25622 | bcode_off_t end_label, continue_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25623 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25624 | body = ast_get_skip(a, pos_after_tag, AST_FOR_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25626 | lookahead = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25627 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25628 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25629 | * Support for `var` declaration in INIT |
Marko Mikulicic |
0:c0ecb8bf28eb | 25630 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25631 | if (tag == AST_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25632 | ast_off_t fvar_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25633 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25634 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25635 | *ppos = lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25636 | fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25638 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25639 | * Iterate through all vars in the given `var` declaration: they are |
Marko Mikulicic |
0:c0ecb8bf28eb | 25640 | * just like assigments here |
Marko Mikulicic |
0:c0ecb8bf28eb | 25641 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25642 | while (*ppos < fvar_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25643 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25644 | /* Only var declarations are allowed (not function declarations) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25645 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25646 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25647 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25649 | /* Just like an assigment */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25650 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25652 | /* INIT is stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25653 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25654 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25655 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25656 | /* normal expression in INIT (not `var` declaration) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25657 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25658 | /* INIT is stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25659 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25660 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25661 | cond = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25662 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25663 | iter = *ppos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25664 | *ppos = body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25665 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25666 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25667 | cond_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25668 | body_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25669 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25670 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25671 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25673 | V7_TRY(compile_expr_builder(bbuilder, a, &iter)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25674 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25675 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25676 | bcode_patch_target(bbuilder, cond_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25678 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25679 | * Handle for(INIT;;ITER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 25680 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25681 | lookahead = cond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25682 | tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25683 | if (tag == AST_NOP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25684 | bcode_op(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25685 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25686 | V7_TRY(compile_expr_builder(bbuilder, a, &cond)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25687 | bcode_op(bbuilder, OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25688 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25689 | body_label = bcode_add_target(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25690 | bcode_patch_target(bbuilder, body_label, body_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25691 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25692 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25693 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25694 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25696 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25697 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25698 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25699 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25700 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25701 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25702 | * for(I in O) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25703 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25704 | * } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25705 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25706 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25707 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25708 | * DUP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25709 | * <O> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25710 | * SWAP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25711 | * STASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25712 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25713 | * PUSH_PROP_ITER_CTX # push initial iteration context |
Marko Mikulicic |
0:c0ecb8bf28eb | 25714 | * TRY_PUSH_LOOP brend |
Marko Mikulicic |
0:c0ecb8bf28eb | 25715 | * loop: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25716 | * NEXT_PROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25717 | * JMP_FALSE end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25718 | * SET_VAR <I> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25719 | * UNSTASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25720 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25721 | * next: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25722 | * STASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25723 | * DROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25724 | * JMP loop |
Marko Mikulicic |
0:c0ecb8bf28eb | 25725 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25726 | * UNSTASH |
Marko Mikulicic |
0:c0ecb8bf28eb | 25727 | * JMP try_pop: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25728 | * brend: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25729 | * # got here after a `break` or `continue` from a loop body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25730 | * JMP_IF_CONTINUE next |
Marko Mikulicic |
0:c0ecb8bf28eb | 25731 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25732 | * # we're not going to `continue`, so, need to remove an |
Marko Mikulicic |
0:c0ecb8bf28eb | 25733 | * # extra stuff that was needed for the NEXT_PROP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25734 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25735 | * SWAP_DROP # drop iteration context |
Marko Mikulicic |
0:c0ecb8bf28eb | 25736 | * SWAP_DROP # drop <O> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25737 | * SWAP_DROP # drop the value preceding the loop |
Marko Mikulicic |
0:c0ecb8bf28eb | 25738 | * try_pop: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25739 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25740 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25741 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25742 | case AST_FOR_IN: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25743 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25744 | bcode_off_t loop_label, loop_target, end_label, brend_label, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25745 | continue_label, pop_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25746 | ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25748 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25749 | /* TODO(mkm) accept any l-value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25750 | if (tag == AST_VAR) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25751 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25752 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25753 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25754 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25755 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25756 | V7_CHECK_INTERNAL(tag == AST_IDENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25757 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25758 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25760 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25761 | * preserve previous statement value. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25762 | * We need to feed the previous value into the stash |
Marko Mikulicic |
0:c0ecb8bf28eb | 25763 | * because it's required for the loop steady state. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25764 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25765 | * The stash register is required to simplify the steady state stack |
Marko Mikulicic |
0:c0ecb8bf28eb | 25766 | * management, in particular the removal of value in 3rd position in case |
Marko Mikulicic |
0:c0ecb8bf28eb | 25767 | * a of not taken exit. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25768 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25769 | * TODO(mkm): consider having a stash OP that moves a value to the stash |
Marko Mikulicic |
0:c0ecb8bf28eb | 25770 | * register instead of copying it. The current behaviour has been |
Marko Mikulicic |
0:c0ecb8bf28eb | 25771 | * optimized for the `assign` use case which seems more common. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25772 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25773 | bcode_op(bbuilder, OP_DUP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25774 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25775 | bcode_op(bbuilder, OP_SWAP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25776 | bcode_op(bbuilder, OP_STASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25777 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25779 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25780 | * OP_NEXT_PROP needs the iteration context, let's push the initial one. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25781 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25782 | bcode_op(bbuilder, OP_PUSH_PROP_ITER_CTX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25784 | brend_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25786 | /* loop: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25787 | loop_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25789 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25790 | * The loop stead state begins with the following stack layout: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25791 | * `( S:v o h )` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25792 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25794 | bcode_op(bbuilder, OP_NEXT_PROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25795 | end_label = bcode_op_target(bbuilder, OP_JMP_FALSE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25796 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25797 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25798 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25799 | * The stash register contains the value of the previous statement, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25800 | * being it the statement before the for..in statement or |
Marko Mikulicic |
0:c0ecb8bf28eb | 25801 | * the previous iteration. We move it to the data stack. It will |
Marko Mikulicic |
0:c0ecb8bf28eb | 25802 | * be replaced by the values of the body statements as usual. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25803 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25804 | bcode_op(bbuilder, OP_UNSTASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25805 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25806 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25807 | * This node is always a NOP, for compatibility |
Marko Mikulicic |
0:c0ecb8bf28eb | 25808 | * with the layout of the AST_FOR node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25809 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25810 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25812 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25813 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25814 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25816 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25817 | * Save the last body statement. If next evaluation of NEXT_PROP returns |
Marko Mikulicic |
0:c0ecb8bf28eb | 25818 | * false, we'll unstash it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25819 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25820 | bcode_op(bbuilder, OP_STASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25821 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25823 | loop_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25824 | bcode_patch_target(bbuilder, loop_label, loop_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25826 | /* end: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25827 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25828 | bcode_op(bbuilder, OP_UNSTASH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25830 | pop_label = bcode_op_target(bbuilder, OP_JMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25831 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25832 | /* brend: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25833 | bcode_patch_target(bbuilder, brend_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25835 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25836 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25837 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25838 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25839 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25840 | bcode_op(bbuilder, OP_SWAP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25842 | /* try_pop: */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25843 | bcode_patch_target(bbuilder, pop_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25844 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25845 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25846 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25847 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25848 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25849 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25850 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25851 | * do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25852 | * B... |
Marko Mikulicic |
0:c0ecb8bf28eb | 25853 | * } while(COND); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25854 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25855 | * -> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25856 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25857 | * TRY_PUSH_LOOP end |
Marko Mikulicic |
0:c0ecb8bf28eb | 25858 | * body: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25859 | * <B> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25860 | * cond: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25861 | * <COND> |
Marko Mikulicic |
0:c0ecb8bf28eb | 25862 | * JMP_TRUE body |
Marko Mikulicic |
0:c0ecb8bf28eb | 25863 | * end: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25864 | * JMP_IF_CONTINUE cond |
Marko Mikulicic |
0:c0ecb8bf28eb | 25865 | * TRY_POP |
Marko Mikulicic |
0:c0ecb8bf28eb | 25866 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25867 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25868 | case AST_DOWHILE: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25869 | bcode_off_t end_label, continue_label, continue_target; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25870 | end = ast_get_skip(a, pos_after_tag, AST_DO_WHILE_COND_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25871 | end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25872 | body_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25873 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25875 | continue_target = bcode_pos(bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25876 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25877 | body_label = bcode_op_target(bbuilder, OP_JMP_TRUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25878 | bcode_patch_target(bbuilder, body_label, body_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25879 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25880 | bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25881 | continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25882 | bcode_patch_target(bbuilder, continue_label, continue_target); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25883 | bcode_op(bbuilder, OP_TRY_POP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25885 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25886 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25887 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25888 | case AST_VAR: { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25889 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25890 | * Var decls are hoisted when the function frame is created. Vars |
Marko Mikulicic |
0:c0ecb8bf28eb | 25891 | * declared inside a `with` or `catch` block belong to the function |
Marko Mikulicic |
0:c0ecb8bf28eb | 25892 | * lexical scope, and although those clauses create an inner frame |
Marko Mikulicic |
0:c0ecb8bf28eb | 25893 | * no new variables should be created in it. A var decl thus |
Marko Mikulicic |
0:c0ecb8bf28eb | 25894 | * behaves as a normal assignment at runtime. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25895 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25896 | lit_t lit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25897 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25898 | while (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25899 | tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25900 | if (tag == AST_FUNC_DECL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25901 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25902 | * function declarations are already set during hoisting (see |
Marko Mikulicic |
0:c0ecb8bf28eb | 25903 | * `compile_local_vars()`), so, skip it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25904 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 25905 | * Plus, they are stack-neutral, so don't forget to set |
Marko Mikulicic |
0:c0ecb8bf28eb | 25906 | * `is_stack_neutral`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25907 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25908 | ast_skip_tree(a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25909 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25910 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25911 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25912 | * compile `var` declaration: basically it looks similar to an |
Marko Mikulicic |
0:c0ecb8bf28eb | 25913 | * assignment, but it differs from an assignment is that it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 25914 | * stack-neutral: `1; var a = 5;` yields `1`, not `5`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25915 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25916 | V7_CHECK_INTERNAL(tag == AST_VAR_DECL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25917 | lit = string_lit(bbuilder, a, pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25918 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25919 | bcode_op_lit(bbuilder, OP_SET_VAR, lit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25920 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25921 | /* `var` declaration is stack-neutral */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25922 | bcode_op(bbuilder, OP_DROP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25923 | bbuilder->v7->is_stack_neutral = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25924 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25925 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25926 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25927 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25928 | case AST_RETURN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25929 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25930 | bcode_op(bbuilder, OP_RET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25931 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25932 | case AST_VALUE_RETURN: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25933 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25934 | bcode_op(bbuilder, OP_RET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25935 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25936 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25937 | *ppos = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25938 | V7_TRY(compile_expr_builder(bbuilder, a, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25939 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25941 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25942 | mbuf_free(&case_labels); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25943 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25944 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25946 | static enum v7_err compile_body(struct bcode_builder *bbuilder, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25947 | ast_off_t start, ast_off_t end, ast_off_t body, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25948 | ast_off_t fvar, ast_off_t *ppos) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25949 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25950 | struct v7 *v7 = bbuilder->v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25952 | #ifndef V7_FORCE_STRICT_MODE |
Marko Mikulicic |
0:c0ecb8bf28eb | 25953 | /* check 'use strict' */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25954 | if (*ppos < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25955 | ast_off_t tmp_pos = body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25956 | if (fetch_tag(v7, bbuilder, a, &tmp_pos, NULL) == AST_USE_STRICT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25957 | bbuilder->bcode->strict_mode = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25958 | /* move `body` offset, effectively removing `AST_USE_STRICT` from it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25959 | body = tmp_pos; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25960 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25961 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25962 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 25963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25964 | /* put initial value for the function body execution */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25965 | bcode_op(bbuilder, OP_PUSH_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25967 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25968 | * populate `bcode->ops` with function's local variable names. Note that we |
Marko Mikulicic |
0:c0ecb8bf28eb | 25969 | * should do this *after* `OP_PUSH_UNDEFINED`, since `compile_local_vars` |
Marko Mikulicic |
0:c0ecb8bf28eb | 25970 | * emits code that assigns the hoisted functions to local variables, and |
Marko Mikulicic |
0:c0ecb8bf28eb | 25971 | * those statements assume that the stack contains `undefined`. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25972 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25973 | V7_TRY(compile_local_vars(bbuilder, a, start, fvar)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25975 | /* compile body */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25976 | *ppos = body; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25977 | V7_TRY(compile_stmts(bbuilder, a, ppos, end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25979 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 25980 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 25982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25983 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 25984 | * Compiles a given script and populates a bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25985 | * The AST must start with an AST_SCRIPT node. |
Marko Mikulicic |
0:c0ecb8bf28eb | 25986 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 25987 | V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 25988 | struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 25989 | ast_off_t pos_after_tag, end, fvar, pos = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25990 | int saved_line_no = v7->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25991 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25992 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25993 | enum ast_tag tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25995 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25996 | v7->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 25997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 25998 | tag = fetch_tag(v7, &bbuilder, a, &pos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 25999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26000 | /* first tag should always be AST_SCRIPT */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26001 | assert(tag == AST_SCRIPT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26002 | (void) tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26003 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26004 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26005 | fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26007 | V7_TRY(compile_body(&bbuilder, a, pos_after_tag - 1, end, pos /* body */, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26008 | fvar, &pos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26009 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26010 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26012 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26014 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 26015 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26016 | fprintf(stderr, "--- script ---\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26017 | dump_bcode(v7, stderr, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26019 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26021 | v7->line_no = saved_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26022 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26023 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26024 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26025 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26026 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26027 | * Compiles a given function and populates a bcode structure. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26028 | * The AST must contain an AST_FUNC node at offset ast_off. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26029 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26030 | V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26031 | ast_off_t *ppos, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26032 | ast_off_t pos_after_tag, start, end, body, fvar; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26033 | const char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26034 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26035 | size_t args_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26036 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26037 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26038 | enum ast_tag tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26039 | size_t names_end = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26040 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26041 | tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26042 | start = pos_after_tag - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26043 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26044 | (void) tag; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26045 | assert(tag == AST_FUNC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26046 | end = ast_get_skip(a, pos_after_tag, AST_END_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26047 | body = ast_get_skip(a, pos_after_tag, AST_FUNC_BODY_SKIP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26048 | fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26050 | /* retrieve function name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26051 | tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26052 | if (tag == AST_IDENT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26053 | /* function name is provided */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26054 | name = ast_get_inlined_data(a, pos_after_tag, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26055 | V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26056 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26057 | /* no name: anonymous function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26058 | V7_TRY(bcode_add_name(&bbuilder, "", 0, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26059 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26061 | /* retrieve function's argument names */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26062 | for (args_cnt = 0; *ppos < body; args_cnt++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26063 | if (args_cnt > V7_ARGS_CNT_MAX) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26064 | /* too many arguments */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26065 | rcode = v7_throwf(v7, SYNTAX_ERROR, "Too many arguments"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26066 | V7_THROW(V7_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26068 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26069 | tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26070 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26071 | * TODO(dfrank): it's not actually an internal error, we get here if |
Marko Mikulicic |
0:c0ecb8bf28eb | 26072 | * we compile e.g. the following: (function(1){}) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26073 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26074 | V7_CHECK_INTERNAL(tag == AST_IDENT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26075 | name = ast_get_inlined_data(a, pos_after_tag, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26076 | V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26078 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26079 | bcode->args_cnt = args_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26080 | bcode->func_name_present = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26081 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26082 | V7_TRY(compile_body(&bbuilder, a, start, end, body, fvar, ppos)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26084 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26085 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26086 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26087 | #ifdef V7_BCODE_DUMP |
Marko Mikulicic |
0:c0ecb8bf28eb | 26088 | if (rcode == V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26089 | fprintf(stderr, "--- function ---\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26090 | dump_bcode(v7, stderr, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26091 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26092 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26094 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26095 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26097 | V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26098 | ast_off_t *ppos, struct bcode *bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26099 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26100 | struct bcode_builder bbuilder; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26101 | int saved_line_no = v7->line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26103 | bcode_builder_init(v7, &bbuilder, bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26104 | v7->line_no = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26106 | rcode = compile_expr_builder(&bbuilder, a, ppos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26107 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26108 | bcode_builder_finalize(&bbuilder); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26109 | v7->line_no = saved_line_no; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26110 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26111 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26113 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26114 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 26115 | #line 1 "v7/src/stdlib.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 26116 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26117 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26118 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 26119 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 26120 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26121 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26122 | /* Amalgamated: #include "common/cs_strtod.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26123 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26124 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26125 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26126 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26127 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26128 | /* Amalgamated: #include "v7/src/stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26129 | /* Amalgamated: #include "v7/src/std_array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26130 | /* Amalgamated: #include "v7/src/std_boolean.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26131 | /* Amalgamated: #include "v7/src/std_date.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26132 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26133 | /* Amalgamated: #include "v7/src/std_function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26134 | /* Amalgamated: #include "v7/src/std_json.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26135 | /* Amalgamated: #include "v7/src/std_math.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26136 | /* Amalgamated: #include "v7/src/std_number.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26137 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26138 | /* Amalgamated: #include "v7/src/std_regex.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26139 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26140 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26141 | /* Amalgamated: #include "v7/src/js_stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26142 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26143 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26144 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26145 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26147 | #ifdef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26148 | void print_str(const char *str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26149 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26151 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26152 | V7_PRIVATE enum v7_err Std_print(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26153 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26154 | int i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26155 | val_t v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26157 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26159 | for (i = 0; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26160 | v = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26161 | if (v7_is_string(v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26162 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26163 | const char *s = v7_get_string(v7, &v, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26164 | printf("%.*s", (int) n, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26165 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26166 | v7_print(v7, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26167 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26168 | printf(" "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26169 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26170 | printf(ENDL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26172 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26175 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26176 | V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, val_t this_obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26177 | int is_json, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26178 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26179 | char buf[100], *p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26180 | struct v7_exec_opts opts; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26181 | memset(&opts, 0x00, sizeof(opts)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26182 | opts.filename = "Eval'd code"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26183 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26184 | if (arg != V7_UNDEFINED) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26185 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26186 | rcode = to_string(v7, arg, NULL, buf, sizeof(buf), &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26187 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26188 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26189 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26191 | /* Fit null terminating byte and quotes */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26192 | if (len >= sizeof(buf) - 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26193 | /* Buffer is not large enough. Allocate a bigger one */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26194 | p = (char *) malloc(len + 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26195 | rcode = to_string(v7, arg, NULL, p, len + 2, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26196 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26197 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26198 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26199 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26201 | v7_set_gc_enabled(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26202 | if (is_json) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26203 | opts.is_json = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26204 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26205 | opts.this_obj = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26206 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26207 | rcode = v7_exec_opt(v7, p, &opts, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26208 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26209 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26210 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26211 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26213 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26214 | if (p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26215 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26216 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26217 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26218 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26219 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26220 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26221 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26222 | V7_PRIVATE enum v7_err Std_eval(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26223 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26224 | v7_val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26225 | return std_eval(v7, arg, this_obj, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26226 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26228 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26229 | V7_PRIVATE enum v7_err Std_parseInt(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26230 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26231 | v7_val_t arg0 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26232 | v7_val_t arg1 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26233 | long sign = 1, base, n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26234 | char buf[20], *p = buf, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26236 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26237 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26238 | arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26239 | arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26240 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26241 | rcode = to_string(v7, arg0, &arg0, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26242 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26243 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26244 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26245 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26246 | rcode = to_number_v(v7, arg1, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26247 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26248 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26251 | if (is_finite(v7, arg1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26252 | base = v7_get_double(v7, arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26253 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26254 | base = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26255 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26257 | if (base == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26258 | base = 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26259 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26261 | if (base < 2 || base > 36) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26262 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26263 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26264 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26265 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26266 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26267 | size_t str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26268 | p = (char *) v7_get_string(v7, &arg0, &str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26270 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26271 | /* Strip leading whitespaces */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26272 | while (*p != '\0' && isspace(*(unsigned char *) p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26273 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26274 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26275 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26276 | if (*p == '+') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26277 | sign = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26278 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26279 | } else if (*p == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26280 | sign = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26281 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26282 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26284 | if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26285 | base = 16; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26286 | p += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26287 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26288 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26289 | n = strtol(p, &end, base); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26290 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26291 | *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, n * sign); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26293 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26294 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26297 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26298 | V7_PRIVATE enum v7_err Std_parseFloat(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26299 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26300 | v7_val_t arg0 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26301 | char buf[20], *p = buf, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26302 | double result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26303 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26304 | rcode = to_primitive(v7, v7_arg(v7, 0), V7_TO_PRIMITIVE_HINT_NUMBER, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26305 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26306 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26307 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26309 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26310 | size_t str_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26311 | p = (char *) v7_get_string(v7, &arg0, &str_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26312 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26313 | rcode = to_string(v7, arg0, NULL, buf, sizeof(buf), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26314 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26315 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26316 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26317 | buf[sizeof(buf) - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26318 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26319 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26320 | while (*p != '\0' && isspace(*(unsigned char *) p)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26321 | p++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26322 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26323 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26324 | result = cs_strtod(p, &end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26325 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26326 | *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26327 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26328 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26329 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26330 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26332 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26333 | V7_PRIVATE enum v7_err Std_isNaN(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26334 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26335 | v7_val_t arg0 = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26336 | rcode = to_number_v(v7, v7_arg(v7, 0), &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26337 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26338 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26339 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26341 | *res = v7_mk_boolean(v7, isnan(v7_get_double(v7, arg0))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26343 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26344 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26345 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26347 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26348 | V7_PRIVATE enum v7_err Std_isFinite(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26349 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26350 | v7_val_t arg0 = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26352 | rcode = to_number_v(v7, v7_arg(v7, 0), &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26353 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26354 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26355 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26356 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26357 | *res = v7_mk_boolean(v7, is_finite(v7, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26358 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26359 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26360 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26361 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26362 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26363 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26364 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 26365 | V7_PRIVATE enum v7_err Std_exit(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26366 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26367 | long exit_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26368 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26369 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26371 | rcode = to_long(v7, v7_arg(v7, 0), 0, &exit_code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26372 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26373 | /* `to_long` has thrown, so, will return 1 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26374 | exit_code = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26375 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26376 | exit(exit_code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26377 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26378 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26379 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26380 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26381 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26382 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26383 | * Initialize standard library. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26384 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26385 | * This function is used only internally, but used in a complicated mix of |
Marko Mikulicic |
0:c0ecb8bf28eb | 26386 | * configurations, hence the commented V7_PRIVATE |
Marko Mikulicic |
0:c0ecb8bf28eb | 26387 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26388 | /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26389 | v7_prop_attr_desc_t attr_internal = |
Marko Mikulicic |
0:c0ecb8bf28eb | 26390 | (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26391 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26392 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26393 | * Ensure the first call to v7_mk_value will use a null proto: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26394 | * {}.__proto__.__proto__ == null |
Marko Mikulicic |
0:c0ecb8bf28eb | 26395 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26396 | v7->vals.object_prototype = mk_object(v7, V7_NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26397 | v7->vals.array_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26398 | v7->vals.boolean_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26399 | v7->vals.string_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26400 | v7->vals.regexp_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26401 | v7->vals.number_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26402 | v7->vals.error_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26403 | v7->vals.global_object = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26404 | v7->vals.date_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26405 | v7->vals.function_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26406 | v7->vals.proxy_prototype = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26408 | set_method(v7, v7->vals.global_object, "eval", Std_eval, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26409 | set_method(v7, v7->vals.global_object, "print", Std_print, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26410 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26411 | set_method(v7, v7->vals.global_object, "exit", Std_exit, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26412 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26413 | set_method(v7, v7->vals.global_object, "parseInt", Std_parseInt, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26414 | set_method(v7, v7->vals.global_object, "parseFloat", Std_parseFloat, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26415 | set_method(v7, v7->vals.global_object, "isNaN", Std_isNaN, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26416 | set_method(v7, v7->vals.global_object, "isFinite", Std_isFinite, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26417 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26418 | v7_def(v7, v7->vals.global_object, "Infinity", 8, attr_internal, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26419 | v7_mk_number(v7, INFINITY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26420 | v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26422 | init_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26423 | init_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26424 | init_error(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26425 | init_boolean(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26426 | #if V7_ENABLE__Math |
Marko Mikulicic |
0:c0ecb8bf28eb | 26427 | init_math(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26428 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26429 | init_string(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26430 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 26431 | init_regex(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26432 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26433 | init_number(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26434 | init_json(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26435 | #if V7_ENABLE__Date |
Marko Mikulicic |
0:c0ecb8bf28eb | 26436 | init_date(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26437 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26438 | init_function(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26439 | init_js_stdlib(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26441 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 26442 | init_proxy(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26443 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26444 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26445 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 26446 | #line 1 "v7/src/js_stdlib.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 26447 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26448 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26449 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 26450 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 26451 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26453 | /* clang-format off */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26454 | /* because clang-format would break JS code, e.g. === converted to == = ... */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26456 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26457 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26458 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26459 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26461 | #define STRINGIFY(x) #x |
Marko Mikulicic |
0:c0ecb8bf28eb | 26462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26463 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26464 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26465 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26467 | static const char js_array_indexOf[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26468 | Object.defineProperty(Array.prototype, "indexOf", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26469 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26470 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26471 | value: function(a, x) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26472 | var i; var r = -1; var b = +x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26473 | if (!b || b < 0) b = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26474 | for (i in this) if (i >= b && (r < 0 || i < r) && this[i] === a) r = +i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26475 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26476 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26478 | static const char js_array_lastIndexOf[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26479 | Object.defineProperty(Array.prototype, "lastIndexOf", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26480 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26481 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26482 | value: function(a, x) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26483 | var i; var r = -1; var b = +x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26484 | if (isNaN(b) || b < 0 || b >= this.length) b = this.length - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26485 | for (i in this) if (i <= b && (r < 0 || i > r) && this[i] === a) r = +i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26486 | return r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26487 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26489 | #if V7_ENABLE__Array__reduce |
Marko Mikulicic |
0:c0ecb8bf28eb | 26490 | static const char js_array_reduce[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26491 | Object.defineProperty(Array.prototype, "reduce", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26492 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26493 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26494 | value: function(a, b) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26495 | var f = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26496 | if (typeof(a) != "function") { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26497 | throw new TypeError(a + " is not a function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26498 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26499 | for (var k in this) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26500 | if (k > this.length) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26501 | if (f == 0 && b === undefined) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26502 | b = this[k]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26503 | f = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26504 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26505 | b = a(b, this[k], k, this); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26506 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26507 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26508 | return b; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26509 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26510 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26512 | static const char js_array_pop[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26513 | Object.defineProperty(Array.prototype, "pop", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26514 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26515 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26516 | value: function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26517 | var i = this.length - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26518 | return this.splice(i, 1)[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26519 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26521 | static const char js_array_shift[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26522 | Object.defineProperty(Array.prototype, "shift", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26523 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26524 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26525 | value: function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26526 | return this.splice(0, 1)[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26527 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26529 | #if V7_ENABLE__Function__call |
Marko Mikulicic |
0:c0ecb8bf28eb | 26530 | static const char js_function_call[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26531 | Object.defineProperty(Function.prototype, "call", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26532 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26533 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26534 | value: function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26535 | var t = arguments.splice(0, 1)[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26536 | return this.apply(t, arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26537 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26538 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26540 | #if V7_ENABLE__Function__bind |
Marko Mikulicic |
0:c0ecb8bf28eb | 26541 | static const char js_function_bind[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26542 | Object.defineProperty(Function.prototype, "bind", { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26543 | writable:true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26544 | configurable: true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26545 | value: function(t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26546 | var f = this; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26547 | return function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26548 | return f.apply(t, arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26549 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26550 | }});); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26551 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26552 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26553 | #if V7_ENABLE__Blob |
Marko Mikulicic |
0:c0ecb8bf28eb | 26554 | static const char js_Blob[] = STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26555 | function Blob(a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26556 | this.a = a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26557 | }); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26558 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26559 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26560 | static const char * const js_functions[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26561 | #if V7_ENABLE__Blob |
Marko Mikulicic |
0:c0ecb8bf28eb | 26562 | js_Blob, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26563 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26564 | #if V7_ENABLE__Function__call |
Marko Mikulicic |
0:c0ecb8bf28eb | 26565 | js_function_call, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26566 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26567 | #if V7_ENABLE__Function__bind |
Marko Mikulicic |
0:c0ecb8bf28eb | 26568 | js_function_bind, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26569 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26570 | #if V7_ENABLE__Array__reduce |
Marko Mikulicic |
0:c0ecb8bf28eb | 26571 | js_array_reduce, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26572 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26573 | js_array_indexOf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26574 | js_array_lastIndexOf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26575 | js_array_pop, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26576 | js_array_shift |
Marko Mikulicic |
0:c0ecb8bf28eb | 26577 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26578 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26579 | V7_PRIVATE void init_js_stdlib(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26580 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26581 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26582 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26583 | for(i = 0; i < (int) ARRAY_SIZE(js_functions); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26584 | if (v7_exec(v7, js_functions[i], &res) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26585 | fprintf(stderr, "ex: %s:\n", js_functions[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26586 | v7_fprintln(stderr, v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26587 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26588 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26589 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26590 | /* TODO(lsm): re-enable in a separate PR */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26591 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 26592 | v7_exec(v7, &res, STRINGIFY( |
Marko Mikulicic |
0:c0ecb8bf28eb | 26593 | Array.prototype.unshift = function() { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26594 | var a = new Array(0, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26595 | Array.prototype.push.apply(a, arguments); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26596 | Array.prototype.splice.apply(this, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26597 | return this.length; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26598 | };)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26599 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26600 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26601 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26602 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26603 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26604 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26605 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 26606 | #line 1 "v7/src/slre.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 26607 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26608 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 26609 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 26610 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 26611 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26612 | * This software is dual-licensed: you can redistribute it and/or modify |
Marko Mikulicic |
0:c0ecb8bf28eb | 26613 | * it under the terms of the GNU General Public License version 2 as |
Marko Mikulicic |
0:c0ecb8bf28eb | 26614 | * published by the Free Software Foundation. For the terms of this |
Marko Mikulicic |
0:c0ecb8bf28eb | 26615 | * license, see <http://www.gnu.org/licenses/>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26616 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26617 | * You are free to use this software under the terms of the GNU General |
Marko Mikulicic |
0:c0ecb8bf28eb | 26618 | * Public License, but WITHOUT ANY WARRANTY; without even the implied |
Marko Mikulicic |
0:c0ecb8bf28eb | 26619 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26620 | * See the GNU General Public License for more details. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26621 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 26622 | * Alternatively, you can license this software under a commercial |
Marko Mikulicic |
0:c0ecb8bf28eb | 26623 | * license, as set out in <https://www.cesanta.com/license>. |
Marko Mikulicic |
0:c0ecb8bf28eb | 26624 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26625 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26626 | /* Amalgamated: #include "v7/src/v7_features.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26627 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26628 | #include <setjmp.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26629 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26630 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26631 | #include <string.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26633 | #ifndef NO_LIBC |
Marko Mikulicic |
0:c0ecb8bf28eb | 26634 | #include <ctype.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 26635 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26636 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26637 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26638 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26640 | /* Limitations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26641 | #define SLRE_MAX_RANGES 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 26642 | #define SLRE_MAX_SETS 16 |
Marko Mikulicic |
0:c0ecb8bf28eb | 26643 | #define SLRE_MAX_REP 0xFFFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 26644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26645 | #define SLRE_MALLOC malloc |
Marko Mikulicic |
0:c0ecb8bf28eb | 26646 | #define SLRE_FREE free |
Marko Mikulicic |
0:c0ecb8bf28eb | 26647 | #define SLRE_THROW(e, err_code) longjmp((e)->jmp_buf, (err_code)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26648 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26649 | static int hex(int c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26650 | if (c >= '0' && c <= '9') return c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26651 | if (c >= 'a' && c <= 'f') return c - 'a' + 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26652 | if (c >= 'A' && c <= 'F') return c - 'A' + 10; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26653 | return -SLRE_INVALID_HEX_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26654 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26656 | int nextesc(const char **p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26657 | const unsigned char *s = (unsigned char *) (*p)++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26658 | switch (*s) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26659 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26660 | return -SLRE_UNTERM_ESC_SEQ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26661 | case 'c': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26662 | ++*p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26663 | return *s & 31; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26664 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26665 | return '\b'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26666 | case 't': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26667 | return '\t'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26668 | case 'n': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26669 | return '\n'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26670 | case 'v': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26671 | return '\v'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26672 | case 'f': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26673 | return '\f'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26674 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26675 | return '\r'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26676 | case '\\': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26677 | return '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26678 | case 'u': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26679 | if (isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 26680 | isxdigit(s[4])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26681 | (*p) += 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26682 | return hex(s[1]) << 12 | hex(s[2]) << 8 | hex(s[3]) << 4 | hex(s[4]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26683 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26684 | return -SLRE_INVALID_HEX_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26685 | case 'x': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26686 | if (isxdigit(s[1]) && isxdigit(s[2])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26687 | (*p) += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26688 | return (hex(s[1]) << 4) | hex(s[2]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26689 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26690 | return -SLRE_INVALID_HEX_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26691 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26692 | return -SLRE_INVALID_ESC_CHAR; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26693 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26694 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26695 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26696 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 26697 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26698 | /* Parser Information */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26699 | struct slre_node { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26700 | unsigned char type; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26701 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26702 | Rune c; /* character */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26703 | struct slre_class *cp; /* class pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26704 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26705 | struct slre_node *x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26706 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26707 | struct slre_node *y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26708 | unsigned char n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26709 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26710 | unsigned char ng; /* not greedy flag */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26711 | unsigned short min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26712 | unsigned short max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26713 | } rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26714 | } y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26715 | } xy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26716 | } par; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26717 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26718 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26719 | struct slre_range { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26720 | unsigned short s, e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26721 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26723 | /* character class, each pair of rune's defines a range */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26724 | struct slre_class { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26725 | struct slre_range *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26726 | struct slre_range spans[SLRE_MAX_RANGES]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26727 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26729 | struct slre_instruction { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26730 | unsigned char opcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26731 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26732 | unsigned char n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26733 | Rune c; /* character */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26734 | struct slre_class *cp; /* class pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26735 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26736 | struct slre_instruction *x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26737 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26738 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26739 | unsigned short min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26740 | unsigned short max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26741 | } rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26742 | struct slre_instruction *y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26743 | } y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26744 | } xy; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26745 | } par; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26746 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26748 | struct slre_prog { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26749 | struct slre_instruction *start, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26750 | unsigned int num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26751 | int flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26752 | struct slre_class charset[SLRE_MAX_SETS]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26753 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26754 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26755 | struct slre_env { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26756 | int is_regex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26757 | const char *src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26758 | const char *src_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26759 | Rune curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26760 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26761 | struct slre_prog *prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26762 | struct slre_node *pstart, *pend; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26764 | struct slre_node *caps[SLRE_MAX_CAPS]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26765 | unsigned int num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26766 | unsigned int sets_num; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26767 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26768 | int lookahead; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26769 | struct slre_class *curr_set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26770 | int min_rep, max_rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26771 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26772 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26773 | ::jmp_buf jmp_buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26774 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 26775 | jmp_buf jmp_buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26776 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 26777 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26778 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26779 | struct slre_thread { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26780 | struct slre_thread *prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26781 | struct slre_instruction *pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26782 | const char *start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26783 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26784 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26786 | enum slre_opcode { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26787 | I_END = 10, /* Terminate: match found */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26788 | I_ANY, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26789 | P_ANY = I_ANY, /* Any character except newline, . */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26790 | I_ANYNL, /* Any character including newline, . */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26791 | I_BOL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26792 | P_BOL = I_BOL, /* Beginning of line, ^ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26793 | I_CH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26794 | P_CH = I_CH, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26795 | I_EOL, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26796 | P_EOL = I_EOL, /* End of line, $ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26797 | I_EOS, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26798 | P_EOS = I_EOS, /* End of string, \0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26799 | I_JUMP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26800 | I_LA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26801 | P_LA = I_LA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26802 | I_LA_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26803 | P_LA_N = I_LA_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26804 | I_LBRA, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26805 | P_BRA = I_LBRA, /* Left bracket, ( */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26806 | I_REF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26807 | P_REF = I_REF, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26808 | I_REP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26809 | P_REP = I_REP, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26810 | I_REP_INI, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26811 | I_RBRA, /* Right bracket, ) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26812 | I_SET, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26813 | P_SET = I_SET, /* Character set, [] */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26814 | I_SET_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26815 | P_SET_N = I_SET_N, /* Negated character set, [] */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26816 | I_SPLIT, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26817 | I_WORD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26818 | P_WORD = I_WORD, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26819 | I_WORD_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26820 | P_WORD_N = I_WORD_N, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26821 | P_ALT, /* Alternation, | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26822 | P_CAT, /* Concatentation, implicit operator */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26823 | L_CH = 256, |
Marko Mikulicic |
0:c0ecb8bf28eb | 26824 | L_COUNT, /* {M,N} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26825 | L_EOS, /* End of string, \0 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26826 | L_LA, /* "(?=" lookahead */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26827 | L_LA_CAP, /* "(?:" lookahead, capture */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26828 | L_LA_N, /* "(?!" negative lookahead */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26829 | L_REF, /* "\1" back-reference */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26830 | L_CHSET, /* character set */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26831 | L_SET_N, /* negative character set */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26832 | L_WORD, /* "\b" word boundary */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26833 | L_WORD_N /* "\B" non-word boundary */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 26834 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26836 | static signed char dec(int c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26837 | if (isdigitrune(c)) return c - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26838 | return SLRE_INVALID_DEC_DIGIT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26839 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26840 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26841 | static unsigned char re_dec_digit(struct slre_env *e, int c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26842 | signed char ret = dec(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26843 | if (ret < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26844 | SLRE_THROW(e, SLRE_INVALID_DEC_DIGIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26845 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26846 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26848 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26849 | static int re_nextc(Rune *r, const char **src, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26850 | *r = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26851 | if (*src >= src_end) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26852 | *src += chartorune(r, *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26853 | if (*r == '\\') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26854 | const char *tmp_s = *src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26855 | int i = nextesc(src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26856 | switch (i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26857 | case -SLRE_INVALID_ESC_CHAR: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26858 | *r = '\\'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26859 | *src = tmp_s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26860 | *src += chartorune(r, *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26861 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26862 | case -SLRE_INVALID_HEX_DIGIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26863 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 26864 | *r = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26866 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26867 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26868 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26869 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26871 | static int re_nextc_raw(Rune *r, const char **src, const char *src_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26872 | *r = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26873 | if (*src >= src_end) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26874 | *src += chartorune(r, *src); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26875 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26876 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26877 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26878 | static int re_nextc_env(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26879 | return re_nextc(&e->curr_rune, &e->src, e->src_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26880 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26882 | static void re_nchset(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26883 | if (e->sets_num >= nelem(e->prog->charset)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26884 | SLRE_THROW(e, SLRE_TOO_MANY_CHARSETS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26885 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26886 | e->curr_set = e->prog->charset + e->sets_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26887 | e->curr_set->end = e->curr_set->spans; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26890 | static void re_rng2set(struct slre_env *e, Rune start, Rune end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26891 | if (start > end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26892 | SLRE_THROW(e, SLRE_INV_CHARSET_RANGE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26893 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26894 | if (e->curr_set->end + 2 == e->curr_set->spans + nelem(e->curr_set->spans)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26895 | SLRE_THROW(e, SLRE_CHARSET_TOO_LARGE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26896 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26897 | e->curr_set->end->s = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26898 | e->curr_set->end->e = end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26899 | e->curr_set->end++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26900 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26901 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26902 | #define re_char2set(e, c) re_rng2set(e, c, c) |
Marko Mikulicic |
0:c0ecb8bf28eb | 26903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26904 | #define re_d_2set(e) re_rng2set(e, '0', '9') |
Marko Mikulicic |
0:c0ecb8bf28eb | 26905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26906 | static void re_D_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26907 | re_rng2set(e, 0, '0' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26908 | re_rng2set(e, '9' + 1, 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26909 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26911 | static void re_s_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26912 | re_char2set(e, 0x9); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26913 | re_rng2set(e, 0xA, 0xD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26914 | re_char2set(e, 0x20); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26915 | re_char2set(e, 0xA0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26916 | re_rng2set(e, 0x2028, 0x2029); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26917 | re_char2set(e, 0xFEFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26918 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26920 | static void re_S_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26921 | re_rng2set(e, 0, 0x9 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26922 | re_rng2set(e, 0xD + 1, 0x20 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26923 | re_rng2set(e, 0x20 + 1, 0xA0 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26924 | re_rng2set(e, 0xA0 + 1, 0x2028 - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26925 | re_rng2set(e, 0x2029 + 1, 0xFEFF - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26926 | re_rng2set(e, 0xFEFF + 1, 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26927 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26929 | static void re_w_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26930 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26931 | re_rng2set(e, 'A', 'Z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26932 | re_char2set(e, '_'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26933 | re_rng2set(e, 'a', 'z'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26934 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26936 | static void re_W_2set(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26937 | re_rng2set(e, 0, '0' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26938 | re_rng2set(e, '9' + 1, 'A' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26939 | re_rng2set(e, 'Z' + 1, '_' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26940 | re_rng2set(e, '_' + 1, 'a' - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26941 | re_rng2set(e, 'z' + 1, 0xFFFF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26942 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26944 | static unsigned char re_endofcount(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26945 | switch (c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26946 | case ',': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26947 | case '}': |
Marko Mikulicic |
0:c0ecb8bf28eb | 26948 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26949 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26950 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26951 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26952 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26953 | static void re_ex_num_overfl(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26954 | SLRE_THROW(e, SLRE_NUM_OVERFLOW); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26955 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26956 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26957 | static enum slre_opcode re_countrep(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26958 | e->min_rep = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26959 | while (e->src < e->src_end && !re_endofcount(e->curr_rune = *e->src++)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26960 | e->min_rep = e->min_rep * 10 + re_dec_digit(e, e->curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26961 | if (e->min_rep >= SLRE_MAX_REP) re_ex_num_overfl(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26964 | if (e->curr_rune != ',') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26965 | e->max_rep = e->min_rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26966 | return L_COUNT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26967 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26968 | e->max_rep = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26969 | while (e->src < e->src_end && (e->curr_rune = *e->src++) != '}') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26970 | e->max_rep = e->max_rep * 10 + re_dec_digit(e, e->curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26971 | if (e->max_rep >= SLRE_MAX_REP) re_ex_num_overfl(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26973 | if (!e->max_rep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26974 | e->max_rep = SLRE_MAX_REP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26975 | return L_COUNT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26976 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26978 | return L_COUNT; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26979 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26980 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26981 | static enum slre_opcode re_lexset(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26982 | Rune ch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26983 | unsigned char esc, ch_fl = 0, dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26984 | enum slre_opcode type = L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26985 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26986 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26987 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26988 | esc = re_nextc_env(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26989 | if (!esc && e->curr_rune == '^') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26990 | type = L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 26991 | esc = re_nextc_env(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 26994 | for (; esc || e->curr_rune != ']'; esc = re_nextc_env(e)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26995 | if (!e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26996 | SLRE_THROW(e, SLRE_MALFORMED_CHARSET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 26997 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 26998 | if (esc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 26999 | if (strchr("DdSsWw", e->curr_rune)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27000 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27001 | re_char2set(e, ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27002 | if (dash_fl) re_char2set(e, '-'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27003 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27004 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27005 | case 'D': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27006 | re_D_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27007 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27008 | case 'd': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27009 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27010 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27011 | case 'S': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27012 | re_S_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27013 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27014 | case 's': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27015 | re_s_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27016 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27017 | case 'W': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27018 | re_W_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27019 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27020 | case 'w': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27021 | re_w_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27022 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27023 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27024 | ch_fl = dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27025 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27027 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27028 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27029 | /* case '-': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27030 | case '\\': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27031 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27032 | case '/': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27033 | case ']': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27034 | case '|': */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27035 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27036 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27037 | e->curr_rune = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27038 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27039 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27040 | e->curr_rune = '\b'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27041 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27042 | /* default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27043 | SLRE_THROW(e->catch_point, e->err_msg, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27044 | SLRE_INVALID_ESC_CHAR); */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27045 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27046 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27047 | if (e->curr_rune == '-') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27048 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27049 | if (dash_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27050 | re_rng2set(e, ch, '-'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27051 | ch_fl = dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27052 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 27053 | dash_fl = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27054 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27055 | ch = '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27056 | ch_fl = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27057 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27058 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27059 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27061 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27062 | if (dash_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27063 | re_rng2set(e, ch, e->curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27064 | ch_fl = dash_fl = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27065 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27066 | re_char2set(e, ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27067 | ch = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27068 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27069 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27070 | ch = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27071 | ch_fl = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27072 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27073 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27074 | if (ch_fl) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27075 | re_char2set(e, ch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27076 | if (dash_fl) re_char2set(e, '-'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27077 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27078 | return type; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27079 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27080 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27081 | static int re_lexer(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27082 | if (re_nextc_env(e)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27083 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27084 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27085 | e->curr_rune = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27086 | return L_EOS; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27087 | case 'b': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27088 | return L_WORD; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27089 | case 'B': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27090 | return L_WORD_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27091 | case 'd': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27092 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27093 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27094 | return L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27095 | case 'D': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27096 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27097 | re_d_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27098 | return L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27099 | case 's': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27100 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27101 | re_s_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27102 | return L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27103 | case 'S': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27104 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27105 | re_s_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27106 | return L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27107 | case 'w': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27108 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27109 | re_w_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27110 | return L_CHSET; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27111 | case 'W': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27112 | re_nchset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27113 | re_w_2set(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27114 | return L_SET_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27115 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27116 | if (isdigitrune(e->curr_rune)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27117 | e->curr_rune -= '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27118 | if (isdigitrune(*e->src)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27119 | e->curr_rune = e->curr_rune * 10 + *e->src++ - '0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27120 | return L_REF; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27121 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27122 | return L_CH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27123 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27125 | if (e->is_regex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27126 | switch (e->curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27127 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27128 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27129 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27130 | case ')': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27131 | case '*': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27132 | case '+': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27133 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27134 | case '?': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27135 | case '^': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27136 | case '|': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27137 | return e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27138 | case '{': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27139 | return re_countrep(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27140 | case '[': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27141 | return re_lexset(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27142 | case '(': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27143 | if (e->src[0] == '?') switch (e->src[1]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27144 | case '=': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27145 | e->src += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27146 | return L_LA; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27147 | case ':': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27148 | e->src += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27149 | return L_LA_CAP; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27150 | case '!': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27151 | e->src += 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27152 | return L_LA_N; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27153 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27154 | return '('; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27155 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27156 | } else if (e->curr_rune == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27157 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27158 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27160 | return L_CH; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27161 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27162 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27163 | #define RE_NEXT(env) (env)->lookahead = re_lexer(env) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27164 | #define RE_ACCEPT(env, t) ((env)->lookahead == (t) ? RE_NEXT(env), 1 : 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27166 | static struct slre_node *re_nnode(struct slre_env *e, int type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27167 | memset(e->pend, 0, sizeof(struct slre_node)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27168 | e->pend->type = type; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27169 | return e->pend++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27170 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27172 | static unsigned char re_isemptynd(struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27173 | if (!nd) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27174 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27175 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27176 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27177 | case P_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27178 | case P_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27179 | case P_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27180 | case P_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27181 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27182 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27183 | case P_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27184 | return re_isemptynd(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27185 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27186 | return re_isemptynd(nd->par.xy.x) && re_isemptynd(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27187 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27188 | return re_isemptynd(nd->par.xy.x) || re_isemptynd(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27189 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27190 | return re_isemptynd(nd->par.xy.x) || !nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27191 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27194 | static struct slre_node *re_nrep(struct slre_env *e, struct slre_node *nd, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27195 | int ng, unsigned short min, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27196 | unsigned short max) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27197 | struct slre_node *rep = re_nnode(e, P_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27198 | if (max == SLRE_MAX_REP && re_isemptynd(nd)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27199 | SLRE_THROW(e, SLRE_INF_LOOP_M_EMP_STR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27200 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27201 | rep->par.xy.y.rp.ng = ng; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27202 | rep->par.xy.y.rp.min = min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27203 | rep->par.xy.y.rp.max = max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27204 | rep->par.xy.x = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27205 | return rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27206 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27207 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27208 | static struct slre_node *re_parser(struct slre_env *e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27209 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27210 | static struct slre_node *re_parse_la(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27211 | struct slre_node *nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27212 | int min, max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27213 | switch (e->lookahead) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27214 | case '^': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27215 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27216 | return re_nnode(e, P_BOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27217 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27218 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27219 | return re_nnode(e, P_EOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27220 | case L_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27221 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27222 | return re_nnode(e, P_EOS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27223 | case L_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27224 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27225 | return re_nnode(e, P_WORD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27226 | case L_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27227 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27228 | return re_nnode(e, P_WORD_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27229 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27230 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27231 | switch (e->lookahead) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27232 | case L_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27233 | nd = re_nnode(e, P_CH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27234 | nd->par.c = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27235 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27236 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27237 | case L_CHSET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27238 | nd = re_nnode(e, P_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27239 | nd->par.cp = e->curr_set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27240 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27241 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27242 | case L_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27243 | nd = re_nnode(e, P_SET_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27244 | nd->par.cp = e->curr_set; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27245 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27246 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27247 | case L_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27248 | nd = re_nnode(e, P_REF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27249 | if (!e->curr_rune || e->curr_rune > e->num_captures || |
Marko Mikulicic |
0:c0ecb8bf28eb | 27250 | !e->caps[e->curr_rune]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27251 | SLRE_THROW(e, SLRE_INVALID_BACK_REFERENCE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27252 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27253 | nd->par.xy.y.n = e->curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27254 | nd->par.xy.x = e->caps[e->curr_rune]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27255 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27256 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27257 | case '.': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27258 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27259 | nd = re_nnode(e, P_ANY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27260 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27261 | case '(': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27262 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27263 | nd = re_nnode(e, P_BRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27264 | if (e->num_captures == SLRE_MAX_CAPS) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27265 | SLRE_THROW(e, SLRE_TOO_MANY_CAPTURES); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27266 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27267 | nd->par.xy.y.n = e->num_captures++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27268 | nd->par.xy.x = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27269 | e->caps[nd->par.xy.y.n] = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27270 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27271 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27272 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27273 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27274 | case L_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27275 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27276 | nd = re_nnode(e, P_LA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27277 | nd->par.xy.x = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27278 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27279 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27280 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27281 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27282 | case L_LA_CAP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27283 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27284 | nd = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27285 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27286 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27287 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27288 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27289 | case L_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27290 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27291 | nd = re_nnode(e, P_LA_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27292 | nd->par.xy.x = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27293 | if (!RE_ACCEPT(e, ')')) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27294 | SLRE_THROW(e, SLRE_UNMATCH_LBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27295 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27296 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27297 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27298 | SLRE_THROW(e, SLRE_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27299 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27300 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27301 | switch (e->lookahead) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27302 | case '*': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27303 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27304 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, SLRE_MAX_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27305 | case '+': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27306 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27307 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), 1, SLRE_MAX_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27308 | case '?': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27309 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27310 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27311 | case L_COUNT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27312 | min = e->min_rep, max = e->max_rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27313 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27314 | if (max < min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27315 | SLRE_THROW(e, SLRE_INVALID_QUANTIFIER); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27316 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27317 | return re_nrep(e, nd, RE_ACCEPT(e, '?'), min, max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27318 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27319 | return nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27322 | static unsigned char re_endofcat(Rune c, int is_regex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27323 | switch (c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27324 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27325 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27326 | case '|': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27327 | case ')': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27328 | if (is_regex) return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27329 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27330 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27331 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27333 | static struct slre_node *re_parser(struct slre_env *e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27334 | struct slre_node *alt = NULL, *cat, *nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27335 | if (!re_endofcat(e->lookahead, e->is_regex)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27336 | cat = re_parse_la(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27337 | while (!re_endofcat(e->lookahead, e->is_regex)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27338 | nd = cat; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27339 | cat = re_nnode(e, P_CAT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27340 | cat->par.xy.x = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27341 | cat->par.xy.y.y = re_parse_la(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27343 | alt = cat; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27344 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27345 | if (e->lookahead == '|') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27346 | RE_NEXT(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27347 | nd = alt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27348 | alt = re_nnode(e, P_ALT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27349 | alt->par.xy.x = nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27350 | alt->par.xy.y.y = re_parser(e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27351 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27352 | return alt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27355 | static unsigned int re_nodelen(struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27356 | unsigned int n = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27357 | if (!nd) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27358 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27359 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27360 | n = 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27361 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27362 | return re_nodelen(nd->par.xy.x) + re_nodelen(nd->par.xy.y.y) + n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27363 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27364 | case P_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27365 | case P_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27366 | return re_nodelen(nd->par.xy.x) + 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27367 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27368 | n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27369 | switch (nd->par.xy.y.rp.min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27370 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27371 | if (!n) return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27372 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27373 | return re_nodelen(nd->par.xy.x) + 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27374 | case 1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27375 | if (!n) return re_nodelen(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27376 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27377 | return re_nodelen(nd->par.xy.x) + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27378 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27379 | n = 4; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27380 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) n++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27381 | return re_nodelen(nd->par.xy.x) + n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27382 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27383 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27384 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27385 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27386 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27387 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27388 | static struct slre_instruction *re_newinst(struct slre_prog *prog, int opcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27389 | memset(prog->end, 0, sizeof(struct slre_instruction)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27390 | prog->end->opcode = opcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27391 | return prog->end++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27392 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27393 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27394 | static void re_compile(struct slre_env *e, struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27395 | struct slre_instruction *inst, *split, *jump, *rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27396 | unsigned int n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27397 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27398 | if (!nd) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27399 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27400 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27401 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27402 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27403 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27404 | jump = re_newinst(e->prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27405 | re_compile(e, nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27406 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27407 | split->par.xy.y.y = jump + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27408 | jump->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27409 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27411 | case P_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27412 | re_newinst(e->prog, I_ANY); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27413 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27415 | case P_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27416 | re_newinst(e->prog, I_BOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27417 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27419 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27420 | inst = re_newinst(e->prog, I_LBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27421 | inst->par.n = nd->par.xy.y.n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27422 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27423 | inst = re_newinst(e->prog, I_RBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27424 | inst->par.n = nd->par.xy.y.n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27425 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27427 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27428 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27429 | re_compile(e, nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27430 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27431 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27432 | case P_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27433 | inst = re_newinst(e->prog, I_CH); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27434 | inst->par.c = nd->par.c; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27435 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27436 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27437 | case P_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27438 | re_newinst(e->prog, I_EOL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27439 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27441 | case P_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27442 | re_newinst(e->prog, I_EOS); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27443 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27445 | case P_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27446 | split = re_newinst(e->prog, I_LA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27447 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27448 | re_newinst(e->prog, I_END); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27449 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27450 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27451 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27452 | case P_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27453 | split = re_newinst(e->prog, I_LA_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27454 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27455 | re_newinst(e->prog, I_END); |
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 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27460 | case P_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27461 | inst = re_newinst(e->prog, I_REF); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27462 | inst->par.n = nd->par.xy.y.n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27463 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27465 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27466 | n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27467 | switch (nd->par.xy.y.rp.min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27468 | case 0: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27469 | if (!n) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27470 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27471 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27472 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27473 | jump = re_newinst(e->prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27474 | jump->par.xy.x = split; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27475 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27476 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27477 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27478 | split->par.xy.y.y = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27479 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27481 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27482 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27483 | case 1: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27484 | if (!n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27485 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27486 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27488 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27489 | inst = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27490 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27491 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27492 | split->par.xy.x = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27493 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27494 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27495 | split->par.xy.y.y = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27496 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27498 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27499 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27500 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27501 | inst = re_newinst(e->prog, I_REP_INI); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27502 | inst->par.xy.y.rp.min = nd->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27503 | inst->par.xy.y.rp.max = n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27504 | rep = re_newinst(e->prog, I_REP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27505 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27506 | re_compile(e, nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27507 | jump = re_newinst(e->prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27508 | jump->par.xy.x = rep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27509 | rep->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27510 | split->par.xy.x = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27511 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27512 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27513 | split->par.xy.y.y = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27514 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27516 | if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27517 | inst = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27518 | split = re_newinst(e->prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27519 | split->par.xy.x = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27520 | split->par.xy.y.y = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27521 | if (nd->par.xy.y.rp.ng) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27522 | split->par.xy.y.y = inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27523 | split->par.xy.x = e->prog->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27524 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27525 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27526 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27527 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27528 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27529 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27530 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27531 | case P_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27532 | inst = re_newinst(e->prog, I_SET); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27533 | inst->par.cp = nd->par.cp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27534 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27535 | case P_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27536 | inst = re_newinst(e->prog, I_SET_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27537 | inst->par.cp = nd->par.cp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27538 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27540 | case P_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27541 | re_newinst(e->prog, I_WORD); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27542 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27543 | case P_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27544 | re_newinst(e->prog, I_WORD_N); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27545 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27546 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27547 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27548 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27549 | #ifdef RE_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 27550 | static void print_set(struct slre_class *cp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27551 | struct slre_range *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27552 | for (p = cp->spans; p < cp->end; p++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27553 | printf("%s", p == cp->spans ? "'" : ",'"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27554 | printf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 27555 | p->s >= 32 && p->s < 127 ? "%c" : (p->s < 256 ? "\\x%02X" : "\\u%04X"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 27556 | p->s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27557 | if (p->s != p->e) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27558 | printf(p->e >= 32 && p->e < 127 ? "-%c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 27559 | : (p->e < 256 ? "-\\x%02X" : "-\\u%04X"), |
Marko Mikulicic |
0:c0ecb8bf28eb | 27560 | p->e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27561 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27562 | printf("'"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27563 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27564 | printf("]"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27565 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27566 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27567 | static void node_print(struct slre_node *nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27568 | if (!nd) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27569 | printf("Empty"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27570 | return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27571 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27572 | switch (nd->type) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27573 | case P_ALT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27574 | printf("{"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27575 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27576 | printf(" | "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27577 | node_print(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27578 | printf("}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27579 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27580 | case P_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27581 | printf("."); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27582 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27583 | case P_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27584 | printf("^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27585 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27586 | case P_BRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27587 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27588 | printf(")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27589 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27590 | case P_CAT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27591 | printf("{"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27592 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27593 | printf(" & "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27594 | node_print(nd->par.xy.y.y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27595 | printf("}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27596 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27597 | case P_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27598 | printf(nd->par.c >= 32 && nd->par.c < 127 ? "'%c'" : "'\\u%04X'", |
Marko Mikulicic |
0:c0ecb8bf28eb | 27599 | nd->par.c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27600 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27601 | case P_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27602 | printf("$"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27603 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27604 | case P_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27605 | printf("\\0"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27606 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27607 | case P_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27608 | printf("LA("); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27609 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27610 | printf(")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27611 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27612 | case P_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27613 | printf("LA_N("); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27614 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27615 | printf(")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27616 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27617 | case P_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27618 | printf("\\%d", nd->par.xy.y.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27619 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27620 | case P_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27621 | node_print(nd->par.xy.x); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27622 | printf(nd->par.xy.y.rp.ng ? "{%d,%d}?" : "{%d,%d}", nd->par.xy.y.rp.min, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27623 | nd->par.xy.y.rp.max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27624 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27625 | case P_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27626 | printf("["); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27627 | print_set(nd->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27628 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27629 | case P_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27630 | printf("[^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27631 | print_set(nd->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27632 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27633 | case P_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27634 | printf("\\b"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27635 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27636 | case P_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27637 | printf("\\B"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27638 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27639 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27640 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27641 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27642 | static void program_print(struct slre_prog *prog) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27643 | struct slre_instruction *inst; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27644 | for (inst = prog->start; inst < prog->end; ++inst) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27645 | printf("%3d: ", inst - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27646 | switch (inst->opcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27647 | case I_END: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27648 | puts("end"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27649 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27650 | case I_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27651 | puts("."); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27652 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27653 | case I_ANYNL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27654 | puts(". | '\\r' | '\\n'"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27655 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27656 | case I_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27657 | puts("^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27658 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27659 | case I_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27660 | printf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 27661 | inst->par.c >= 32 && inst->par.c < 127 ? "'%c'\n" : "'\\u%04X'\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 27662 | inst->par.c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27663 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27664 | case I_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27665 | puts("$"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27666 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27667 | case I_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27668 | puts("\\0"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27669 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27670 | case I_JUMP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27671 | printf("-->%d\n", inst->par.xy.x - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27672 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27673 | case I_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27674 | printf("la %d %d\n", inst->par.xy.x - prog->start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27675 | inst->par.xy.y.y - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27676 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27677 | case I_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27678 | printf("la_n %d %d\n", inst->par.xy.x - prog->start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27679 | inst->par.xy.y.y - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27680 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27681 | case I_LBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27682 | printf("( %d\n", inst->par.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27683 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27684 | case I_RBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27685 | printf(") %d\n", inst->par.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27686 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27687 | case I_SPLIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27688 | printf("-->%d | -->%d\n", inst->par.xy.x - prog->start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27689 | inst->par.xy.y.y - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27690 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27691 | case I_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27692 | printf("\\%d\n", inst->par.n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27693 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27694 | case I_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27695 | printf("repeat -->%d\n", inst->par.xy.x - prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27696 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27697 | case I_REP_INI: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27698 | printf("init_rep %d %d\n", inst->par.xy.y.rp.min, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27699 | inst->par.xy.y.rp.min + inst->par.xy.y.rp.max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27700 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27701 | case I_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27702 | printf("["); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27703 | print_set(inst->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27704 | puts(""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27705 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27706 | case I_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27707 | printf("[^"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27708 | print_set(inst->par.cp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27709 | puts(""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27710 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27711 | case I_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27712 | puts("\\w"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27713 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27714 | case I_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27715 | puts("\\W"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27716 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27717 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27718 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27719 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27720 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 27721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27722 | int slre_compile(const char *pat, size_t pat_len, const char *flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27723 | volatile size_t fl_len, struct slre_prog **pr, int is_regex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27724 | struct slre_env e; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27725 | struct slre_node *nd; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27726 | struct slre_instruction *split, *jump; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27727 | int err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27728 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27729 | e.is_regex = is_regex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27730 | e.prog = (struct slre_prog *) SLRE_MALLOC(sizeof(struct slre_prog)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27731 | e.pstart = e.pend = |
Marko Mikulicic |
0:c0ecb8bf28eb | 27732 | (struct slre_node *) SLRE_MALLOC(sizeof(struct slre_node) * pat_len * 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27733 | e.prog->flags = is_regex ? SLRE_FLAG_RE : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27734 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27735 | if ((err_code = setjmp(e.jmp_buf)) != SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27736 | SLRE_FREE(e.pstart); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27737 | SLRE_FREE(e.prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27738 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27739 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27740 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27741 | while (fl_len--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27742 | switch (flags[fl_len]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27743 | case 'g': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27744 | e.prog->flags |= SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27745 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27746 | case 'i': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27747 | e.prog->flags |= SLRE_FLAG_I; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27748 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27749 | case 'm': |
Marko Mikulicic |
0:c0ecb8bf28eb | 27750 | e.prog->flags |= SLRE_FLAG_M; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27751 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27752 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27753 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27754 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27755 | e.src = pat; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27756 | e.src_end = pat + pat_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27757 | e.sets_num = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27758 | e.num_captures = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27759 | /*e.flags = flags;*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27760 | memset(e.caps, 0, sizeof(e.caps)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27761 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27762 | RE_NEXT(&e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27763 | nd = re_parser(&e); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27764 | if (e.lookahead == ')') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27765 | SLRE_THROW(&e, SLRE_UNMATCH_RBR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27767 | if (e.lookahead != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27768 | SLRE_THROW(&e, SLRE_SYNTAX_ERROR); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27769 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27770 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27771 | e.prog->num_captures = e.num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27772 | e.prog->start = e.prog->end = (struct slre_instruction *) SLRE_MALLOC( |
Marko Mikulicic |
0:c0ecb8bf28eb | 27773 | (re_nodelen(nd) + 6) * sizeof(struct slre_instruction)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27775 | split = re_newinst(e.prog, I_SPLIT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27776 | split->par.xy.x = split + 3; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27777 | split->par.xy.y.y = split + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27778 | re_newinst(e.prog, I_ANYNL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27779 | jump = re_newinst(e.prog, I_JUMP); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27780 | jump->par.xy.x = split; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27781 | re_newinst(e.prog, I_LBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27782 | re_compile(&e, nd); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27783 | re_newinst(e.prog, I_RBRA); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27784 | re_newinst(e.prog, I_END); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27786 | #ifdef RE_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 27787 | node_print(nd); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27788 | putchar('\n'); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27789 | program_print(e.prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27790 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 27791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27792 | SLRE_FREE(e.pstart); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27793 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27794 | if (pr != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27795 | *pr = e.prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27796 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27797 | slre_free(e.prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27798 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27799 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27800 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27801 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27802 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27803 | void slre_free(struct slre_prog *prog) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27804 | if (prog) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27805 | SLRE_FREE(prog->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27806 | SLRE_FREE(prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27807 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27808 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27810 | static struct slre_thread *re_newthread(struct slre_thread *t, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27811 | struct slre_instruction *pc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27812 | const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27813 | struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27814 | struct slre_thread *new_thread = |
Marko Mikulicic |
0:c0ecb8bf28eb | 27815 | (struct slre_thread *) SLRE_MALLOC(sizeof(struct slre_thread)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27816 | if (new_thread != NULL) new_thread->prev = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27817 | t->pc = pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27818 | t->start = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27819 | t->loot = *loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27820 | return new_thread; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27823 | static struct slre_thread *get_prev_thread(struct slre_thread *t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27824 | struct slre_thread *tmp_thr = t->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27825 | SLRE_FREE(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27826 | return tmp_thr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27829 | static void free_threads(struct slre_thread *t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27830 | while (t->prev != NULL) t = get_prev_thread(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27831 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27832 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27833 | static unsigned char re_match(struct slre_instruction *pc, const char *current, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27834 | const char *end, const char *bol, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27835 | unsigned int flags, struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27836 | struct slre_loot sub, tmpsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27837 | Rune c, r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27838 | struct slre_range *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27839 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27840 | struct slre_thread thread, *curr_thread, *tmp_thr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27841 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27842 | /* queue initial thread */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27843 | thread.prev = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27844 | curr_thread = re_newthread(&thread, pc, current, loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27845 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27846 | /* run threads in stack order */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27847 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27848 | curr_thread = get_prev_thread(curr_thread); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27849 | pc = curr_thread->pc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27850 | current = curr_thread->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27851 | sub = curr_thread->loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27852 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27853 | switch (pc->opcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27854 | case I_END: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27855 | memcpy(loot->caps, sub.caps, sizeof loot->caps); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27856 | free_threads(curr_thread); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27857 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27858 | case I_ANY: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27859 | case I_ANYNL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27860 | if (current < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27861 | current += chartorune(&c, current); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27862 | if (c && !(pc->opcode == I_ANY && isnewline(c))) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27864 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27865 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27866 | case I_BOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27867 | if (current == bol) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27868 | if ((flags & SLRE_FLAG_M) && isnewline(current[-1])) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27869 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27870 | case I_CH: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27871 | if (current < end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27872 | current += chartorune(&c, current); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27873 | if (c && |
Marko Mikulicic |
0:c0ecb8bf28eb | 27874 | (c == pc->par.c || ((flags & SLRE_FLAG_I) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 27875 | tolowerrune(c) == tolowerrune(pc->par.c)))) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27876 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27878 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27879 | case I_EOL: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27880 | if (current >= end) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27881 | if ((flags & SLRE_FLAG_M) && isnewline(*current)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27882 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27883 | case I_EOS: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27884 | if (current >= end) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27885 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27886 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27887 | case I_JUMP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27888 | pc = pc->par.xy.x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27889 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27890 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27891 | case I_LA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27892 | if (re_match(pc->par.xy.x, current, end, bol, flags, &sub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27893 | pc = pc->par.xy.y.y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27894 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27895 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27896 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27897 | case I_LA_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27898 | tmpsub = sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27899 | if (!re_match(pc->par.xy.x, current, end, bol, flags, &tmpsub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27900 | pc = pc->par.xy.y.y; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27901 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27902 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27903 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27905 | case I_LBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27906 | sub.caps[pc->par.n].start = current; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27907 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27909 | case I_REF: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27910 | i = sub.caps[pc->par.n].end - sub.caps[pc->par.n].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27911 | if (flags & SLRE_FLAG_I) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27912 | int num = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27913 | const char *s = current, *p = sub.caps[pc->par.n].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27914 | Rune rr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27915 | for (; num && *s && *p; num--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27916 | s += chartorune(&r, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27917 | p += chartorune(&rr, p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27918 | if (tolowerrune(r) != tolowerrune(rr)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27919 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27920 | if (num) goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27921 | } else if (strncmp(current, sub.caps[pc->par.n].start, i)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27922 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27923 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27924 | if (i > 0) current += i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27925 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27926 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27927 | case I_REP: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27928 | if (pc->par.xy.y.rp.min) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27929 | pc->par.xy.y.rp.min--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27930 | pc++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27931 | } else if (!pc->par.xy.y.rp.max--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27932 | pc = pc->par.xy.x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27933 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27934 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27935 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27937 | case I_REP_INI: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27938 | (pc + 1)->par.xy.y.rp.min = pc->par.xy.y.rp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27939 | (pc + 1)->par.xy.y.rp.max = pc->par.xy.y.rp.max; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27940 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27941 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27942 | case I_RBRA: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27943 | sub.caps[pc->par.n].end = current; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27944 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27946 | case I_SET: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27947 | case I_SET_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27948 | if (current >= end) goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27949 | current += chartorune(&c, current); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27950 | if (!c) goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27951 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27952 | i = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27953 | for (p = pc->par.cp->spans; i && p < pc->par.cp->end; p++) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27954 | if (flags & SLRE_FLAG_I) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27955 | for (r = p->s; r <= p->e; ++r) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27956 | if (tolowerrune(c) == tolowerrune(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27957 | i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27958 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27959 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27960 | } else if (p->s <= c && c <= p->e) |
Marko Mikulicic |
0:c0ecb8bf28eb | 27961 | i = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27962 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27963 | if (pc->opcode == I_SET) i = !i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27964 | if (i) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27965 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27967 | case I_SPLIT: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27968 | tmp_thr = curr_thread; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27969 | curr_thread = |
Marko Mikulicic |
0:c0ecb8bf28eb | 27970 | re_newthread(curr_thread, pc->par.xy.y.y, current, &sub); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27971 | if (curr_thread == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 27972 | fprintf(stderr, "re_match: no memory for thread!\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27973 | free_threads(tmp_thr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27974 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27975 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27976 | pc = pc->par.xy.x; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27977 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27979 | case I_WORD: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27980 | case I_WORD_N: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27981 | i = (current > bol && iswordchar(current[-1])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27982 | if (iswordchar(current[0])) i = !i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27983 | if (pc->opcode == I_WORD_N) i = !i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27984 | if (i) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27985 | /* goto no_match; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 27986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27987 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27988 | goto no_match; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27989 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27990 | pc++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27991 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27992 | no_match: |
Marko Mikulicic |
0:c0ecb8bf28eb | 27993 | ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27994 | } while (curr_thread->prev != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 27995 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 27996 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 27997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 27998 | int slre_exec(struct slre_prog *prog, int flag_g, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 27999 | const char *end, struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28000 | struct slre_loot tmpsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28001 | const char *st = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28003 | if (!loot) loot = &tmpsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28004 | memset(loot, 0, sizeof(*loot)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28005 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28006 | if (!flag_g) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28007 | loot->num_captures = prog->num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28008 | return !re_match(prog->start, start, end, start, prog->flags, loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28009 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28010 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28011 | while (re_match(prog->start, st, end, start, prog->flags, &tmpsub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28012 | unsigned int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28013 | st = tmpsub.caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28014 | for (i = 0; i < prog->num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28015 | struct slre_cap *l = &loot->caps[loot->num_captures + i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28016 | struct slre_cap *s = &tmpsub.caps[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28017 | l->start = s->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28018 | l->end = s->end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28019 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28020 | loot->num_captures += prog->num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28021 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28022 | return !loot->num_captures; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28023 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28024 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28025 | int slre_replace(struct slre_loot *loot, const char *src, size_t src_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28026 | const char *rstr, size_t rstr_len, struct slre_loot *dstsub) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28027 | int size = 0, n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28028 | Rune curr_rune; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28029 | const char *const rstr_end = rstr + rstr_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28031 | memset(dstsub, 0, sizeof(*dstsub)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28032 | while (rstr < rstr_end && !(n = re_nextc_raw(&curr_rune, &rstr, rstr_end)) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 28033 | curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28034 | int sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28035 | if (n < 0) return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28036 | if (curr_rune == '$') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28037 | n = re_nextc(&curr_rune, &rstr, rstr_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28038 | if (n < 0) return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28039 | switch (curr_rune) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28040 | case '&': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28041 | sz = loot->caps[0].end - loot->caps[0].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28042 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28043 | dstsub->caps[dstsub->num_captures++] = loot->caps[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28044 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28045 | case '0': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28046 | case '1': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28047 | case '2': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28048 | case '3': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28049 | case '4': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28050 | case '5': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28051 | case '6': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28052 | case '7': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28053 | case '8': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28054 | case '9': { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28055 | int sbn = dec(curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28056 | if (0 == sbn && rstr[0] && isdigitrune(rstr[0])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28057 | n = re_nextc(&curr_rune, &rstr, rstr_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28058 | if (n < 0) return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28059 | sz = dec(curr_rune); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28060 | sbn = sbn * 10 + sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28061 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28062 | if (sbn >= loot->num_captures) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28063 | sz = loot->caps[sbn].end - loot->caps[sbn].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28064 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28065 | dstsub->caps[dstsub->num_captures++] = loot->caps[sbn]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28066 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28068 | case '`': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28069 | sz = loot->caps[0].start - src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28070 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28071 | dstsub->caps[dstsub->num_captures].start = src; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28072 | dstsub->caps[dstsub->num_captures++].end = loot->caps[0].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28073 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28074 | case '\'': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28075 | sz = src + src_len - loot->caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28076 | size += sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28077 | dstsub->caps[dstsub->num_captures].start = loot->caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28078 | dstsub->caps[dstsub->num_captures++].end = loot->caps[0].end + sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28079 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28080 | case '$': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28081 | size++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28082 | dstsub->caps[dstsub->num_captures].start = rstr - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28083 | dstsub->caps[dstsub->num_captures++].end = rstr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28084 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28085 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28086 | return SLRE_BAD_CHAR_AFTER_USD; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28087 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28088 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28089 | char tmps[300], *d = tmps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28090 | size += (sz = runetochar(d, &curr_rune)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28091 | if (!dstsub->num_captures || |
Marko Mikulicic |
0:c0ecb8bf28eb | 28092 | dstsub->caps[dstsub->num_captures - 1].end != rstr - sz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28093 | dstsub->caps[dstsub->num_captures].start = rstr - sz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28094 | dstsub->caps[dstsub->num_captures++].end = rstr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28095 | } else |
Marko Mikulicic |
0:c0ecb8bf28eb | 28096 | dstsub->caps[dstsub->num_captures - 1].end = rstr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28097 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28098 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28099 | return size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28102 | int slre_match(const char *re, size_t re_len, const char *flags, size_t fl_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28103 | const char *str, size_t str_len, struct slre_loot *loot) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28104 | struct slre_prog *prog = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28105 | int res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28106 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28107 | if ((res = slre_compile(re, re_len, flags, fl_len, &prog, 1)) == SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28108 | res = slre_exec(prog, prog->flags & SLRE_FLAG_G, str, str + str_len, loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28109 | slre_free(prog); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28110 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28112 | return res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28113 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28115 | int slre_get_flags(struct slre_prog *crp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28116 | return crp->flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28117 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28118 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28119 | #ifdef SLRE_TEST |
Marko Mikulicic |
0:c0ecb8bf28eb | 28120 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28121 | #include <errno.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28123 | static const char *err_code_to_str(int err_code) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28124 | static const char *ar[] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28125 | "no error", "invalid decimal digit", "invalid hex digit", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28126 | "invalid escape character", "invalid unterminated escape sequence", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28127 | "syntax error", "unmatched left parenthesis", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28128 | "unmatched right parenthesis", "numeric overflow", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28129 | "infinite loop empty string", "too many charsets", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28130 | "invalid charset range", "charset is too large", "malformed charset", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28131 | "invalid back reference", "too many captures", "invalid quantifier", |
Marko Mikulicic |
0:c0ecb8bf28eb | 28132 | "bad character after $"}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28134 | typedef char static_assertion_err_codes_out_of_sync |
Marko Mikulicic |
0:c0ecb8bf28eb | 28135 | [2 * !!(((sizeof(ar) / sizeof(ar[0])) == SLRE_BAD_CHAR_AFTER_USD + 1)) - |
Marko Mikulicic |
0:c0ecb8bf28eb | 28136 | 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28137 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28138 | return err_code >= 0 && err_code < (int) (sizeof(ar) / sizeof(ar[0])) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28139 | ? ar[err_code] |
Marko Mikulicic |
0:c0ecb8bf28eb | 28140 | : "invalid error code"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28141 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28143 | #define RE_TEST_STR_SIZE 2000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28145 | static unsigned get_flags(const char *ch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28146 | unsigned int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28147 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28148 | while (*ch != '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28149 | switch (*ch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28150 | case 'g': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28151 | flags |= SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28152 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28153 | case 'i': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28154 | flags |= SLRE_FLAG_I; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28155 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28156 | case 'm': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28157 | flags |= SLRE_FLAG_M; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28158 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28159 | case 'r': |
Marko Mikulicic |
0:c0ecb8bf28eb | 28160 | flags |= SLRE_FLAG_RE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28161 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28162 | default: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28163 | return flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28164 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28165 | ch++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28166 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28167 | return flags; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28168 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28170 | static void show_usage_and_exit(char *argv[]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28171 | fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28172 | fprintf(stderr, "%s\n", "OPTIONS:"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28173 | fprintf(stderr, "%s\n", " -p <regex_pattern> Regex pattern"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28174 | fprintf(stderr, "%s\n", " -o <regex_flags> Combination of g,i,m"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28175 | fprintf(stderr, "%s\n", " -s <string> String to match"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28176 | fprintf(stderr, "%s\n", " -f <file_name> Match lines from file"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28177 | fprintf(stderr, "%s\n", " -n <cap_no> Show given capture"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28178 | fprintf(stderr, "%s\n", " -r <replace_str> Replace given capture"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28179 | fprintf(stderr, "%s\n", " -v Show verbose stats"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28180 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28181 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28182 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28183 | static int process_line(struct slre_prog *pr, const char *flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28184 | const char *line, const char *cap_no, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28185 | const char *replace, const char *verbose) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28186 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28187 | unsigned int fl = flags == NULL ? 0 : get_flags(flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28188 | int i, n = cap_no == NULL ? -1 : atoi(cap_no), err_code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28189 | struct slre_cap *cap = &loot.caps[n]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28191 | err_code = |
Marko Mikulicic |
0:c0ecb8bf28eb | 28192 | slre_exec(pr, pr->flags & SLRE_FLAG_G, line, line + strlen(line), &loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28193 | if (err_code == SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28194 | if (n >= 0 && n < loot.num_captures && replace != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28195 | struct slre_cap *cap = &loot.caps[n]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28196 | printf("%.*s", (int) (cap->start - line), line); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28197 | printf("%s", replace); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28198 | printf("%.*s", (int) ((line + strlen(line)) - cap->end), cap->end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28199 | } else if (n >= 0 && n < loot.num_captures) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28200 | printf("%.*s\n", (int) (cap->end - cap->start), cap->start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28203 | if (verbose != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28204 | fprintf(stderr, "%s\n", "Captures:"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28205 | for (i = 0; i < loot.num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28206 | fprintf(stderr, "%d [%.*s]\n", i, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28207 | (int) (loot.caps[i].end - loot.caps[i].start), |
Marko Mikulicic |
0:c0ecb8bf28eb | 28208 | loot.caps[i].start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28209 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28210 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28211 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28213 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28214 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28215 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28216 | int main(int argc, char **argv) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28217 | const char *str = NULL, *pattern = NULL, *replace = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28218 | const char *flags = "", *file_name = NULL, *cap_no = NULL, *verbose = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28219 | struct slre_prog *pr = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28220 | int i, err_code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28222 | /* Execute inline code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28223 | for (i = 1; i < argc; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28224 | if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28225 | pattern = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28226 | } else if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28227 | flags = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28228 | } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28229 | str = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28230 | } else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28231 | file_name = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28232 | } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28233 | cap_no = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28234 | } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28235 | replace = argv[++i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28236 | } else if (strcmp(argv[i], "-v") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28237 | verbose = ""; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28238 | } else if (strcmp(argv[i], "-h") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28239 | show_usage_and_exit(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28240 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28241 | show_usage_and_exit(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28242 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28243 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28244 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28245 | if (pattern == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28246 | fprintf(stderr, "%s\n", "-p option is mandatory"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28247 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28248 | } else if ((err_code = slre_compile(pattern, strlen(pattern), flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28249 | strlen(flags), &pr, 1)) != SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28250 | fprintf(stderr, "slre_compile(%s): %s\n", argv[0], |
Marko Mikulicic |
0:c0ecb8bf28eb | 28251 | err_code_to_str(err_code)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28252 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28253 | } else if (str != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28254 | err_code = process_line(pr, flags, str, cap_no, replace, verbose); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28255 | } else if (file_name != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28256 | FILE *fp = strcmp(file_name, "-") == 0 ? stdin : fopen(file_name, "rb"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28257 | char line[20 * 1024]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28258 | if (fp == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28259 | fprintf(stderr, "Cannot open %s: %s\n", file_name, strerror(errno)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28260 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28261 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28262 | /* Return success if at least one line matches */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28263 | err_code = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28264 | while (fgets(line, sizeof(line), fp) != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28265 | if (process_line(pr, flags, line, cap_no, replace, verbose) == |
Marko Mikulicic |
0:c0ecb8bf28eb | 28266 | SLRE_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28267 | err_code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28268 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28269 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28270 | fclose(fp); /* If fp == stdin, it is safe to close, too */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28271 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28272 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28273 | fprintf(stderr, "%s\n", "Please specify one of -s or -f options"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28274 | exit(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28275 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28276 | slre_free(pr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28278 | return err_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28279 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28280 | #endif /* SLRE_TEST */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28282 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28283 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 28284 | #line 1 "v7/src/heapusage.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 28285 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28286 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28287 | * Copyright (c) 2014-2016 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 28288 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 28289 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28290 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28291 | #include <stdlib.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28292 | #include <stdio.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28293 | #include <assert.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 28294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28295 | #if defined(V7_HEAPUSAGE_ENABLE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28296 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28297 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28298 | * A flag that is set by GC before allocating its buffers, so we can |
Marko Mikulicic |
0:c0ecb8bf28eb | 28299 | * distinguish these buffers from other allocations |
Marko Mikulicic |
0:c0ecb8bf28eb | 28300 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28301 | volatile int heap_dont_count = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28302 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28303 | extern void *__real_malloc(size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28304 | extern void *__real_calloc(size_t num, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28305 | extern void *__real_realloc(void *p, size_t size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28306 | extern void __real_free(void *p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28307 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28308 | /* TODO(dfrank): make it dynamically allocated from heap */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28309 | #define CELLS_CNT (1024 * 32) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28310 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28311 | typedef struct cell { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28312 | void *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28313 | unsigned dont_count : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28314 | unsigned size : 31; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28315 | } cell_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28317 | typedef struct alloc_registry { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28318 | size_t used_cells_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28319 | size_t allocated_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28320 | size_t real_used_cells_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28321 | size_t real_allocated_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28322 | cell_t cells[CELLS_CNT]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28323 | } alloc_registry_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28324 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28325 | static alloc_registry_t registry = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28327 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28328 | * Make a record about an allocated buffer `p` of size `size` |
Marko Mikulicic |
0:c0ecb8bf28eb | 28329 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28330 | static void cell_allocated(void *p, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28331 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28332 | int cell_num = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28333 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28334 | if (p != NULL && size != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28335 | /* TODO(dfrank): make it dynamically allocated from heap */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28336 | assert(registry.real_used_cells_cnt < CELLS_CNT); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28337 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28338 | for (i = 0; i < CELLS_CNT; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28339 | if (registry.cells[i].p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28340 | cell_num = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28341 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28343 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28344 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28345 | assert(cell_num != -1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28347 | registry.cells[cell_num].p = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28348 | registry.cells[cell_num].size = size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28349 | registry.cells[cell_num].dont_count = !!heap_dont_count; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28351 | registry.real_allocated_size += size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28352 | registry.real_used_cells_cnt += 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28353 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28354 | if (!heap_dont_count) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28355 | registry.allocated_size += size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28356 | registry.used_cells_cnt += 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28357 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28358 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28359 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28360 | printf("alloc=0x%lx, size=%lu, total=%lu\n", (unsigned long)p, size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28361 | registry.allocated_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28362 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28364 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28365 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28366 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28367 | * Delete a record about an allocated buffer `p`. If our registry does not |
Marko Mikulicic |
0:c0ecb8bf28eb | 28368 | * contain anything about the given pointer, the call is ignored. We can't |
Marko Mikulicic |
0:c0ecb8bf28eb | 28369 | * generate an error because shared libraries still use unwrapped heap |
Marko Mikulicic |
0:c0ecb8bf28eb | 28370 | * functions, so we can face "unknown" pointers. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28371 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28372 | static void cell_freed(void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28373 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28374 | int cell_num = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28376 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28377 | assert(registry.real_used_cells_cnt > 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28379 | for (i = 0; i < CELLS_CNT; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28380 | if (registry.cells[i].p == p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28381 | cell_num = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28382 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28383 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28384 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28385 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28386 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28387 | * NOTE: it would be nice to have `assert(cell_num != -1);`, but |
Marko Mikulicic |
0:c0ecb8bf28eb | 28388 | * unfortunately not all allocations are wrapped: shared libraries will |
Marko Mikulicic |
0:c0ecb8bf28eb | 28389 | * still use unwrapped mallocs, so we might get unknown pointers here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28390 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28391 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28392 | if (cell_num != -1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28393 | registry.real_allocated_size -= registry.cells[cell_num].size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28394 | registry.real_used_cells_cnt -= 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28395 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28396 | if (!registry.cells[cell_num].dont_count) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28397 | registry.allocated_size -= registry.cells[cell_num].size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28398 | registry.used_cells_cnt -= 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28399 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28400 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28401 | registry.cells[cell_num].p = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28402 | registry.cells[cell_num].size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28403 | registry.cells[cell_num].dont_count = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28404 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28405 | #if 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28406 | printf("free=0x%lx, total=%lu\n", (unsigned long)p, registry.allocated_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28407 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28408 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28409 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28410 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28412 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28413 | * Wrappers of the standard heap functions |
Marko Mikulicic |
0:c0ecb8bf28eb | 28414 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28415 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28416 | void *__wrap_malloc(size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28417 | void *ret = __real_malloc(size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28418 | cell_allocated(ret, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28419 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28420 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28422 | void *__wrap_calloc(size_t num, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28423 | void *ret = __real_calloc(num, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28424 | cell_allocated(ret, num * size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28425 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28428 | void *__wrap_realloc(void *p, size_t size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28429 | void *ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28430 | cell_freed(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28431 | ret = __real_realloc(p, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28432 | cell_allocated(ret, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28433 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28434 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28436 | void __wrap_free(void *p) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28437 | __real_free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28438 | cell_freed(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28439 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28441 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28442 | * Small API to get some stats, see header file for details |
Marko Mikulicic |
0:c0ecb8bf28eb | 28443 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28445 | size_t heapusage_alloc_size(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28446 | return registry.allocated_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28447 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28449 | size_t heapusage_allocs_cnt(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28450 | return registry.used_cells_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28451 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28452 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28453 | #endif /* V7_HEAPUSAGE_ENABLE */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28454 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 28455 | #line 1 "v7/src/cyg_profile.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 28456 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28457 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28458 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 28459 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 28460 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28462 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28463 | * This file contains GCC/clang instrumentation callbacks. The actual |
Marko Mikulicic |
0:c0ecb8bf28eb | 28464 | * code in these callbacks depends on enabled features. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28465 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 28466 | * Currently, the code from different subsystems is embedded right into |
Marko Mikulicic |
0:c0ecb8bf28eb | 28467 | * callbacks for performance reasons. It would be probably more elegant |
Marko Mikulicic |
0:c0ecb8bf28eb | 28468 | * to have subsystem-specific functions that will be called from these |
Marko Mikulicic |
0:c0ecb8bf28eb | 28469 | * callbacks, but since the callbacks are called really a lot (on each v7 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28470 | * function call), I decided it's better to inline the code right here. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28471 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28473 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28474 | /* Amalgamated: #include "v7/src/cyg_profile.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28475 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28476 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28477 | #if defined(V7_CYG_PROFILE_ON) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28478 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28479 | #if defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28480 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28481 | #define CALL_TRACE_SIZE 32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 28482 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28483 | typedef struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28484 | uint16_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28485 | uint16_t missed_cnt; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28486 | void *addresses[CALL_TRACE_SIZE]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28487 | } call_trace_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28489 | static call_trace_t call_trace = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28490 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28491 | NOINSTR |
Marko Mikulicic |
0:c0ecb8bf28eb | 28492 | void call_trace_print(const char *prefix, const char *suffix, size_t skip_cnt, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28493 | size_t max_cnt) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28494 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28495 | if (call_trace.missed_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28496 | fprintf(stderr, "missed calls! (%d) ", (int) call_trace.missed_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28498 | if (prefix != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28499 | fprintf(stderr, "%s", prefix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28500 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28501 | for (i = (int) call_trace.size - 1 - skip_cnt; i >= 0; i--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28502 | fprintf(stderr, " %lx", (unsigned long) call_trace.addresses[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28503 | if (max_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28504 | if (--max_cnt == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28505 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28506 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28507 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28508 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28509 | if (suffix != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28510 | fprintf(stderr, "%s", suffix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28511 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28512 | fprintf(stderr, "\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28513 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28514 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28515 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28517 | #ifndef IRAM |
Marko Mikulicic |
0:c0ecb8bf28eb | 28518 | #define IRAM |
Marko Mikulicic |
0:c0ecb8bf28eb | 28519 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28521 | #ifndef NOINSTR |
Marko Mikulicic |
0:c0ecb8bf28eb | 28522 | #define NOINSTR __attribute__((no_instrument_function)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28523 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28525 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28526 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28527 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28528 | IRAM NOINSTR void __cyg_profile_func_enter(void *this_fn, void *call_site); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28529 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28530 | IRAM NOINSTR void __cyg_profile_func_exit(void *this_fn, void *call_site); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28532 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28533 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28534 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28536 | IRAM void __cyg_profile_func_enter(void *this_fn, void *call_site) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28537 | #if defined(V7_STACK_GUARD_MIN_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28538 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28539 | static int profile_enter = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28540 | void *fp = __builtin_frame_address(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28542 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28544 | if (profile_enter || v7_sp_limit == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28546 | profile_enter++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28547 | if (v7_head != NULL && fp < v7_head->sp_lwm) v7_head->sp_lwm = fp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28548 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28549 | if (((int) fp - (int) v7_sp_limit) < V7_STACK_GUARD_MIN_SIZE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28550 | printf("fun %p sp %p limit %p left %d\n", this_fn, fp, v7_sp_limit, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28551 | (int) fp - (int) v7_sp_limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28552 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28553 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28554 | profile_enter--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28555 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28556 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28557 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28558 | #if defined(V7_ENABLE_GC_CHECK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28559 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28560 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28561 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28562 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28563 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28565 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28566 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28567 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28568 | struct stack_track_ctx *ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28569 | void *fp = __builtin_frame_address(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28571 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28572 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28574 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28575 | * TODO(dfrank): it actually won't work for multiple instances of v7 running |
Marko Mikulicic |
0:c0ecb8bf28eb | 28576 | * in parallel threads. We need to know the exact v7 instance for which |
Marko Mikulicic |
0:c0ecb8bf28eb | 28577 | * current function is called, but so far I failed to find a way to do this. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28578 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28579 | for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28580 | for (ctx = v7->stack_track_ctx; ctx != NULL; ctx = ctx->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28581 | /* commented because it fails on legal code compiled with -O3 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28582 | /*assert(fp <= ctx->start);*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28584 | if (fp < ctx->max) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28585 | ctx->max = fp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28586 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28587 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28588 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28589 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28590 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28592 | #if defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28593 | if (call_trace.size < CALL_TRACE_SIZE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28594 | call_trace.addresses[call_trace.size] = this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28595 | call_trace.size++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28596 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28597 | call_trace.missed_cnt++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28598 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28599 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28600 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28601 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28602 | IRAM void __cyg_profile_func_exit(void *this_fn, void *call_site) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28603 | #if defined(V7_STACK_GUARD_MIN_SIZE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28604 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28605 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28606 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28607 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28608 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28610 | #if defined(V7_ENABLE_GC_CHECK) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28611 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28612 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28613 | void *fp = __builtin_frame_address(1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28614 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28615 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28616 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28618 | for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28619 | v7_val_t **vp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28620 | if (v7->owned_values.buf == NULL) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28621 | vp = (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - |
Marko Mikulicic |
0:c0ecb8bf28eb | 28622 | sizeof(v7_val_t *)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28624 | for (; (char *) vp >= v7->owned_values.buf; vp--) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28625 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28626 | * Check if a variable belongs to a dead stack frame. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28627 | * Addresses lower than the parent frame belong to the |
Marko Mikulicic |
0:c0ecb8bf28eb | 28628 | * stack frame of the function about to return. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28629 | * But the heap also usually below the stack and |
Marko Mikulicic |
0:c0ecb8bf28eb | 28630 | * we don't know the end of the stack. But this hook |
Marko Mikulicic |
0:c0ecb8bf28eb | 28631 | * is called at each function return, so we have |
Marko Mikulicic |
0:c0ecb8bf28eb | 28632 | * to check only up to the maximum stack frame size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28633 | * let's arbitrarily but reasonably set that at 8k. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28634 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28635 | if ((void *) *vp <= fp && (void *) *vp > (fp + 8196)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28636 | fprintf(stderr, "Found owned variable after return\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28637 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28638 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28639 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28640 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28642 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28643 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28644 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28645 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28646 | (void) this_fn; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28647 | (void) call_site; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28648 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28649 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28651 | #if defined(V7_ENABLE_CALL_TRACE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28652 | if (call_trace.missed_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28653 | call_trace.missed_cnt--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28654 | } else if (call_trace.size > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28655 | if (call_trace.addresses[call_trace.size - 1] != this_fn) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28656 | abort(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28657 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28658 | call_trace.size--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28659 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28660 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28661 | * We may get here if calls to `__cyg_profile_func_exit()` and |
Marko Mikulicic |
0:c0ecb8bf28eb | 28662 | * `__cyg_profile_func_enter()` are unbalanced. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28663 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 28664 | * TODO(dfrank) understand, why in the beginning of the program execution |
Marko Mikulicic |
0:c0ecb8bf28eb | 28665 | * we get here. I was sure this should be impossible. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28666 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28667 | /* abort(); */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28668 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28669 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28670 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28672 | #if defined(V7_ENABLE_STACK_TRACKING) |
Marko Mikulicic |
0:c0ecb8bf28eb | 28673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28674 | void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28675 | /* insert new context at the head of the list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28676 | ctx->next = v7->stack_track_ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28677 | v7->stack_track_ctx = ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28679 | /* init both `max` and `start` to the current frame pointer */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28680 | ctx->max = ctx->start = __builtin_frame_address(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28681 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28682 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28683 | int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28684 | int diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28686 | /* this function can be called only for the head context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28687 | assert(v7->stack_track_ctx == ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28689 | diff = (int) ((char *) ctx->start - (char *) ctx->max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28690 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28691 | /* remove context from the linked list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28692 | v7->stack_track_ctx = ctx->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28694 | return (int) diff; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28695 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28697 | #endif /* V7_ENABLE_STACK_TRACKING */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28698 | #endif /* V7_CYG_PROFILE_ON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28699 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 28700 | #line 1 "v7/src/std_object.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 28701 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28702 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28703 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 28704 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 28705 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28706 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28707 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28708 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28709 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28710 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28711 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28712 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28713 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28714 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28715 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28716 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28717 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28718 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28719 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28720 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28721 | #if V7_ENABLE__Object__getPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 28722 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28723 | V7_PRIVATE enum v7_err Obj_getPrototypeOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28724 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28725 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28726 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28727 | if (!v7_is_object(arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28728 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 28729 | v7_throwf(v7, TYPE_ERROR, "Object.getPrototypeOf called on non-object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28730 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28731 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28732 | *res = v7_get_proto(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28733 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28734 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28735 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28736 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28737 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28739 | #if V7_ENABLE__Object__isPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 28740 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28741 | V7_PRIVATE enum v7_err Obj_isPrototypeOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28742 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28743 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28744 | val_t proto = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28746 | *res = v7_mk_boolean(v7, is_prototype_of(v7, obj, proto)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28747 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28748 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28750 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28751 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28752 | #if V7_ENABLE__Object__getOwnPropertyNames || V7_ENABLE__Object__keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 28753 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28754 | * Hack to ensure that the iteration order of the keys array is consistent |
Marko Mikulicic |
0:c0ecb8bf28eb | 28755 | * with the iteration order if properties in `for in` |
Marko Mikulicic |
0:c0ecb8bf28eb | 28756 | * This will be obsoleted when arrays will have a special object type. |
Marko Mikulicic |
0:c0ecb8bf28eb | 28757 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28758 | static void _Obj_append_reverse(struct v7 *v7, struct v7_property *p, val_t res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28759 | int i, v7_prop_attr_t ignore_flags) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28760 | while (p && p->attributes & ignore_flags) p = p->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28761 | if (p == NULL) return; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28762 | if (p->next) _Obj_append_reverse(v7, p->next, res, i + 1, ignore_flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28764 | v7_array_set(v7, res, i, p->name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28765 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28766 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28767 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28768 | static enum v7_err _Obj_ownKeys(struct v7 *v7, unsigned int ignore_flags, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28769 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28770 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28771 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28773 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28775 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28776 | rcode = v7_throwf(v7, TYPE_ERROR, "Object.keys called on non-object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28777 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28778 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28779 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28780 | _Obj_append_reverse(v7, get_object_struct(obj)->properties, *res, 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28781 | ignore_flags); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28783 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28784 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28786 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28787 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28788 | #if V7_ENABLE__Object__hasOwnProperty || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28789 | V7_ENABLE__Object__propertyIsEnumerable || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28790 | V7_ENABLE__Object__getOwnPropertyDescriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 28791 | static enum v7_err _Obj_getOwnProperty(struct v7 *v7, val_t obj, val_t name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28792 | struct v7_property **res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28793 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28794 | char name_buf[512]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28795 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28796 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28797 | rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28798 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28799 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28800 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28802 | *res = v7_get_own_property(v7, obj, name_buf, name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28804 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28805 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28806 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28807 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28809 | #if V7_ENABLE__Object__keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 28810 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28811 | V7_PRIVATE enum v7_err Obj_keys(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28812 | return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28813 | res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28815 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28817 | #if V7_ENABLE__Object__getOwnPropertyNames |
Marko Mikulicic |
0:c0ecb8bf28eb | 28818 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28819 | V7_PRIVATE enum v7_err Obj_getOwnPropertyNames(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28820 | return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28822 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28823 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28824 | #if V7_ENABLE__Object__getOwnPropertyDescriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 28825 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28826 | V7_PRIVATE enum v7_err Obj_getOwnPropertyDescriptor(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28827 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28828 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28829 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28830 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28831 | val_t name = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28832 | val_t desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28833 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28834 | rcode = _Obj_getOwnProperty(v7, obj, name, &prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28835 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28836 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28837 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28839 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28840 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28841 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28843 | desc = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28844 | v7_set(v7, desc, "value", 5, prop->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28845 | v7_set(v7, desc, "writable", 8, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28846 | v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_WRITABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28847 | v7_set(v7, desc, "enumerable", 10, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28848 | v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28849 | V7_PROPERTY_NON_ENUMERABLE)))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28850 | v7_set(v7, desc, "configurable", 12, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28851 | v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_CONFIGURABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28852 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28853 | *res = desc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28855 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28856 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28857 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28858 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28859 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28860 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28861 | static enum v7_err o_set_attr(struct v7 *v7, val_t desc, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28862 | size_t n, v7_prop_attr_desc_t *pattrs_delta, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28863 | v7_prop_attr_desc_t flag_true, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28864 | v7_prop_attr_desc_t flag_false) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28865 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28867 | val_t v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28868 | rcode = v7_get_throwing(v7, desc, name, n, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28869 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28870 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28871 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28872 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28873 | if (v7_is_truthy(v7, v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28874 | *pattrs_delta |= flag_true; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28875 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28876 | *pattrs_delta |= flag_false; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28877 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28879 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28880 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28881 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28882 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28883 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28884 | static enum v7_err _Obj_defineProperty(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28885 | const char *name, int name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28886 | val_t desc, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28887 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28888 | val_t val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28889 | v7_prop_attr_desc_t attrs_desc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28890 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28891 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 28892 | * get provided value, or set `V7_DESC_PRESERVE_VALUE` flag if no value is |
Marko Mikulicic |
0:c0ecb8bf28eb | 28893 | * provided at all |
Marko Mikulicic |
0:c0ecb8bf28eb | 28894 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28895 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28896 | struct v7_property *prop = v7_get_property(v7, desc, "value", 5); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28897 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28898 | /* no value is provided */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28899 | attrs_desc |= V7_DESC_PRESERVE_VALUE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28900 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28901 | /* value is provided: use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28902 | rcode = v7_property_value(v7, desc, prop, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28903 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28904 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28906 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28907 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28908 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28909 | /* Examine given properties, and set appropriate flags for `def_property` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28911 | rcode = o_set_attr(v7, desc, "enumerable", 10, &attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28912 | V7_DESC_ENUMERABLE(1), V7_DESC_ENUMERABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28913 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28914 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28917 | rcode = o_set_attr(v7, desc, "writable", 8, &attrs_desc, V7_DESC_WRITABLE(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 28918 | V7_DESC_WRITABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28919 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28920 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28921 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28922 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28923 | rcode = o_set_attr(v7, desc, "configurable", 12, &attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28924 | V7_DESC_CONFIGURABLE(1), V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28925 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28926 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28927 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28929 | /* TODO(dfrank) : add getter/setter support */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28930 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28931 | /* Finally, do the job on defining the property */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 28932 | rcode = def_property(v7, obj, name, name_len, attrs_desc, val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28933 | 0 /*not assign*/, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28934 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28935 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28936 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28937 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28938 | *res = obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28939 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28940 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28941 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28942 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28943 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28944 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28945 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28946 | V7_PRIVATE enum v7_err Obj_defineProperty(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28947 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28948 | val_t obj = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28949 | val_t name = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28950 | val_t desc = v7_arg(v7, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28951 | char name_buf[512]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28952 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28954 | if (!v7_is_object(obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28955 | rcode = v7_throwf(v7, TYPE_ERROR, "object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28956 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28957 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28958 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28959 | rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28960 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28961 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28963 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28964 | rcode = _Obj_defineProperty(v7, obj, name_buf, name_len, desc, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28965 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28966 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28967 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28968 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28969 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28971 | #if V7_ENABLE__Object__create || V7_ENABLE__Object__defineProperties |
Marko Mikulicic |
0:c0ecb8bf28eb | 28972 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 28973 | static enum v7_err o_define_props(struct v7 *v7, val_t obj, val_t descs, |
Marko Mikulicic |
0:c0ecb8bf28eb | 28974 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28975 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28976 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28978 | if (!v7_is_object(descs)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28979 | rcode = v7_throwf(v7, TYPE_ERROR, "object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28980 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28981 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28982 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28983 | for (p = get_object_struct(descs)->properties; p; p = p->next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28984 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28985 | const char *s = v7_get_string(v7, &p->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 28986 | if (p->attributes & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 28987 | continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28988 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28989 | rcode = _Obj_defineProperty(v7, obj, s, n, p->value, 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 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 28995 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 28996 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 28997 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 28998 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 28999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29000 | #if V7_ENABLE__Object__defineProperties |
Marko Mikulicic |
0:c0ecb8bf28eb | 29001 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29002 | V7_PRIVATE enum v7_err Obj_defineProperties(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29003 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29004 | val_t descs = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29005 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29006 | *res = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29007 | descs = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29008 | rcode = o_define_props(v7, *res, descs, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29009 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29010 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29011 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29012 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29013 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29014 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29015 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29016 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29017 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29018 | #if V7_ENABLE__Object__create |
Marko Mikulicic |
0:c0ecb8bf28eb | 29019 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29020 | V7_PRIVATE enum v7_err Obj_create(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29021 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29022 | val_t proto = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29023 | val_t descs = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29024 | if (!v7_is_null(proto) && !v7_is_object(proto)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29025 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29026 | "Object prototype may only be an Object or null"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29027 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29028 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29029 | *res = mk_object(v7, proto); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29030 | if (v7_is_object(descs)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29031 | rcode = o_define_props(v7, *res, descs, res); |
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 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29037 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29038 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29039 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29040 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29042 | #if V7_ENABLE__Object__propertyIsEnumerable |
Marko Mikulicic |
0:c0ecb8bf28eb | 29043 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29044 | V7_PRIVATE enum v7_err Obj_propertyIsEnumerable(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29045 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29046 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29047 | struct v7_property *prop; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29048 | val_t name = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29050 | rcode = _Obj_getOwnProperty(v7, this_obj, name, &prop); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29051 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29052 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29053 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29054 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29055 | if (prop == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29056 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29057 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29058 | *res = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29059 | v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29060 | V7_PROPERTY_NON_ENUMERABLE))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29061 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29063 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29064 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29065 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29066 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29067 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29068 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29070 | #if V7_ENABLE__Object__hasOwnProperty |
Marko Mikulicic |
0:c0ecb8bf28eb | 29071 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29072 | V7_PRIVATE enum v7_err Obj_hasOwnProperty(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29073 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29074 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29075 | val_t name = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29076 | struct v7_property *ptmp = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29077 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29078 | rcode = _Obj_getOwnProperty(v7, this_obj, name, &ptmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29079 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29080 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29083 | *res = v7_mk_boolean(v7, ptmp != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29084 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29085 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29086 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29087 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29088 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29089 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29091 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29092 | V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29093 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29094 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29095 | struct v7_property *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29097 | *res = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29098 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29099 | if (v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29100 | /* res is `this_obj` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29101 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29102 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29104 | p = v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29105 | if (p != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29106 | *res = p->value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29107 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29108 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29110 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29111 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29112 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29113 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29114 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29115 | V7_PRIVATE enum v7_err Obj_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29116 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29117 | val_t ctor, name, this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29118 | char buf[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29119 | const char *str = "Object"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29120 | size_t name_len = ~0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29121 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29122 | if (v7_is_undefined(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29123 | str = "Undefined"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29124 | } else if (v7_is_null(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29125 | str = "Null"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29126 | } else if (v7_is_number(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29127 | str = "Number"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29128 | } else if (v7_is_boolean(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29129 | str = "Boolean"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29130 | } else if (v7_is_string(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29131 | str = "String"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29132 | } else if (v7_is_callable(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29133 | str = "Function"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29134 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29135 | rcode = v7_get_throwing(v7, this_obj, "constructor", ~0, &ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29136 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29137 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29138 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29140 | if (!v7_is_undefined(ctor)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29141 | rcode = v7_get_throwing(v7, ctor, "name", ~0, &name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29142 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29143 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29144 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29146 | if (!v7_is_undefined(name)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29147 | size_t tmp_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29148 | const char *tmp_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29149 | tmp_str = v7_get_string(v7, &name, &tmp_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29150 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29151 | * objects constructed with an anonymous constructor are represented as |
Marko Mikulicic |
0:c0ecb8bf28eb | 29152 | * Object, ch11/11.1/11.1.1/S11.1.1_A4.2.js |
Marko Mikulicic |
0:c0ecb8bf28eb | 29153 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29154 | if (tmp_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29155 | str = tmp_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29156 | name_len = tmp_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29157 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29158 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29159 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29160 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29162 | if (name_len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29163 | name_len = strlen(str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29164 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29166 | c_snprintf(buf, sizeof(buf), "[object %.*s]", (int) name_len, str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29167 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29168 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29169 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29170 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29171 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29172 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29173 | #if V7_ENABLE__Object__preventExtensions |
Marko Mikulicic |
0:c0ecb8bf28eb | 29174 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29175 | V7_PRIVATE enum v7_err Obj_preventExtensions(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29176 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29177 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29178 | if (!v7_is_object(arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29179 | rcode = v7_throwf(v7, TYPE_ERROR, "Object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29180 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29181 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29182 | get_object_struct(arg)->attributes |= V7_OBJ_NOT_EXTENSIBLE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29183 | *res = arg; |
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__isExtensible |
Marko Mikulicic |
0:c0ecb8bf28eb | 29191 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29192 | V7_PRIVATE enum v7_err Obj_isExtensible(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29193 | enum v7_err rcode = V7_OK; |
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( |
Marko Mikulicic |
0:c0ecb8bf28eb | 29202 | v7, !(get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29203 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29204 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29205 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29206 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29207 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29209 | #if V7_ENABLE__Object__isFrozen || V7_ENABLE__Object__isSealed |
Marko Mikulicic |
0:c0ecb8bf28eb | 29210 | static enum v7_err is_rigid(struct v7 *v7, v7_val_t *res, int is_frozen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29211 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29212 | int ok = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29213 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29214 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29215 | if (!v7_is_object(arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29216 | rcode = v7_throwf(v7, TYPE_ERROR, "Object expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29217 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29218 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29220 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29222 | if (get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29223 | v7_prop_attr_t attrs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29224 | struct prop_iter_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29225 | memset(&ctx, 0, sizeof(ctx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29226 | V7_TRY2(init_prop_iter_ctx(v7, arg, 1, &ctx), clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29227 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29228 | V7_TRY2(next_prop(v7, &ctx, NULL, NULL, &attrs, &ok), clean_iter); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29229 | if (!ok) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29230 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29232 | if (!(attrs & V7_PROPERTY_NON_CONFIGURABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29233 | goto clean_iter; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29234 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29235 | if (is_frozen) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29236 | if (!(attrs & V7_PROPERTY_SETTER) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29237 | !(attrs & V7_PROPERTY_NON_WRITABLE)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29238 | goto clean_iter; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29239 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29240 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29241 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29243 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29244 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29245 | clean_iter: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29246 | v7_destruct_prop_iter_ctx(v7, &ctx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29247 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29248 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29249 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29250 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29251 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29252 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29253 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29254 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29255 | #if V7_ENABLE__Object__isSealed |
Marko Mikulicic |
0:c0ecb8bf28eb | 29256 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29257 | V7_PRIVATE enum v7_err Obj_isSealed(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29258 | return is_rigid(v7, res, 0 /* is_frozen */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29259 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29260 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29262 | #if V7_ENABLE__Object__isFrozen |
Marko Mikulicic |
0:c0ecb8bf28eb | 29263 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29264 | V7_PRIVATE enum v7_err Obj_isFrozen(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29265 | return is_rigid(v7, res, 1 /* is_frozen */); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29266 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29267 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29268 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29269 | static const char js_function_Object[] = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29270 | "function Object(v) {" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29271 | "if (typeof v === 'boolean') return new Boolean(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29272 | "if (typeof v === 'number') return new Number(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29273 | "if (typeof v === 'string') return new String(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29274 | "if (typeof v === 'date') return new Date(v);" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29275 | "}"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29276 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29277 | V7_PRIVATE void init_object(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29278 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29279 | val_t object, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29280 | /* TODO(mkm): initialize global object without requiring a parser */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29281 | rcode = v7_exec(v7, js_function_Object, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29282 | assert(rcode == V7_OK); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29283 | #if defined(NDEBUG) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29284 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29285 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29286 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29287 | object = v7_get(v7, v7->vals.global_object, "Object", 6); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29288 | v7_set(v7, object, "prototype", 9, v7->vals.object_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29289 | v7_def(v7, v7->vals.object_prototype, "constructor", 11, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29290 | V7_DESC_ENUMERABLE(0), object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29291 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29292 | set_method(v7, v7->vals.object_prototype, "toString", Obj_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29293 | #if V7_ENABLE__Object__getPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 29294 | set_cfunc_prop(v7, object, "getPrototypeOf", Obj_getPrototypeOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29295 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29296 | #if V7_ENABLE__Object__getOwnPropertyDescriptor |
Marko Mikulicic |
0:c0ecb8bf28eb | 29297 | set_cfunc_prop(v7, object, "getOwnPropertyDescriptor", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29298 | Obj_getOwnPropertyDescriptor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29299 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29300 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29301 | /* defineProperty is currently required to perform stdlib initialization */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29302 | set_method(v7, object, "defineProperty", Obj_defineProperty, 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29303 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29304 | #if V7_ENABLE__Object__defineProperties |
Marko Mikulicic |
0:c0ecb8bf28eb | 29305 | set_cfunc_prop(v7, object, "defineProperties", Obj_defineProperties); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29306 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29307 | #if V7_ENABLE__Object__create |
Marko Mikulicic |
0:c0ecb8bf28eb | 29308 | set_cfunc_prop(v7, object, "create", Obj_create); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29309 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29310 | #if V7_ENABLE__Object__keys |
Marko Mikulicic |
0:c0ecb8bf28eb | 29311 | set_cfunc_prop(v7, object, "keys", Obj_keys); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29312 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29313 | #if V7_ENABLE__Object__getOwnPropertyNames |
Marko Mikulicic |
0:c0ecb8bf28eb | 29314 | set_cfunc_prop(v7, object, "getOwnPropertyNames", Obj_getOwnPropertyNames); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29315 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29316 | #if V7_ENABLE__Object__preventExtensions |
Marko Mikulicic |
0:c0ecb8bf28eb | 29317 | set_method(v7, object, "preventExtensions", Obj_preventExtensions, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29318 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29319 | #if V7_ENABLE__Object__isExtensible |
Marko Mikulicic |
0:c0ecb8bf28eb | 29320 | set_method(v7, object, "isExtensible", Obj_isExtensible, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29321 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29322 | #if V7_ENABLE__Object__isSealed |
Marko Mikulicic |
0:c0ecb8bf28eb | 29323 | set_method(v7, object, "isSealed", Obj_isSealed, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29324 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29325 | #if V7_ENABLE__Object__isFrozen |
Marko Mikulicic |
0:c0ecb8bf28eb | 29326 | set_method(v7, object, "isFrozen", Obj_isFrozen, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29327 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29328 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29329 | #if V7_ENABLE__Object__propertyIsEnumerable |
Marko Mikulicic |
0:c0ecb8bf28eb | 29330 | set_cfunc_prop(v7, v7->vals.object_prototype, "propertyIsEnumerable", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29331 | Obj_propertyIsEnumerable); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29332 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29333 | #if V7_ENABLE__Object__hasOwnProperty |
Marko Mikulicic |
0:c0ecb8bf28eb | 29334 | set_cfunc_prop(v7, v7->vals.object_prototype, "hasOwnProperty", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29335 | Obj_hasOwnProperty); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29336 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29337 | #if V7_ENABLE__Object__isPrototypeOf |
Marko Mikulicic |
0:c0ecb8bf28eb | 29338 | set_cfunc_prop(v7, v7->vals.object_prototype, "isPrototypeOf", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29339 | Obj_isPrototypeOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29340 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29341 | set_cfunc_prop(v7, v7->vals.object_prototype, "valueOf", Obj_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29342 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29343 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29344 | #line 1 "v7/src/std_error.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29345 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29346 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29347 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29348 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29349 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29351 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29352 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29353 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29354 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29355 | /* Amalgamated: #include "v7/src/std_error.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29356 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29357 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29358 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29359 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29361 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29362 | * TODO(dfrank): make the top of v7->call_frame to represent the current |
Marko Mikulicic |
0:c0ecb8bf28eb | 29363 | * frame, and thus get rid of the `CUR_LINENO()` |
Marko Mikulicic |
0:c0ecb8bf28eb | 29364 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29365 | #ifndef V7_DISABLE_LINE_NUMBERS |
Marko Mikulicic |
0:c0ecb8bf28eb | 29366 | #define CALLFRAME_LINENO(call_frame) ((call_frame)->line_no) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29367 | #define CUR_LINENO() (v7->line_no) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29368 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 29369 | #define CALLFRAME_LINENO(call_frame) 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 29370 | #define CUR_LINENO() 0 |
Marko Mikulicic |
0:c0ecb8bf28eb | 29371 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29373 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29374 | V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29376 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29377 | static int printf_stack_line(char *p, size_t len, struct bcode *bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29378 | int line_no, const char *leading) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29379 | int ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29380 | const char *fn = bcode_get_filename(bcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29381 | if (fn == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29382 | fn = "<no filename>"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29383 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29385 | if (bcode->func_name_present) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29386 | /* this is a function's bcode: let's show the function's name as well */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29387 | char *funcname; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29388 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29389 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29390 | * read first name from the bcode ops, which is the function name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29391 | * since `func_name_present` is set |
Marko Mikulicic |
0:c0ecb8bf28eb | 29392 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29393 | bcode_next_name(bcode->ops.p, &funcname, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29394 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29395 | /* Check if it's an anonymous function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29396 | if (funcname[0] == '\0') { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29397 | funcname = (char *) "<anonymous>"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29398 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29399 | ret = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29400 | snprintf(p, len, "%s at %s (%s:%d)", leading, funcname, fn, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29401 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29402 | /* it's a file's bcode: show only filename and line number */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29403 | ret = snprintf(p, len, "%s at %s:%d", leading, fn, line_no); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29404 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29405 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29406 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29408 | static int printf_stack_line_cfunc(char *p, size_t len, v7_cfunction_t *cfunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29409 | const char *leading) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29410 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29412 | #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29413 | int name_len = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29414 | snprintf(NULL, 0, "cfunc_%p", (void *) cfunc) + 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29415 | char *buf = (char *) malloc(name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29417 | snprintf(buf, name_len, "cfunc_%p", (void *) cfunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29418 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 29419 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29420 | * We need this mode only for ecma test reporting, so that the |
Marko Mikulicic |
0:c0ecb8bf28eb | 29421 | * report is not different from one run to another |
Marko Mikulicic |
0:c0ecb8bf28eb | 29422 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29423 | char *buf = (char *) "cfunc"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29424 | (void) cfunc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29425 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29427 | ret = snprintf(p, len, "%s at %s", leading, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29428 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29429 | #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29430 | free(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29431 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29432 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29433 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29434 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29435 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29436 | static int print_stack_trace(char *p, size_t len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29437 | struct v7_call_frame_base *call_frame) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29438 | char *p_cur = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29439 | int total_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29441 | assert(call_frame->type_mask == V7_CALL_FRAME_MASK_CFUNC && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29442 | ((struct v7_call_frame_cfunc *) call_frame)->cfunc == Error_ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29443 | call_frame = call_frame->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29444 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29445 | while (call_frame != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29446 | int cur_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29447 | const char *leading = (total_len ? "\n" : ""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29448 | size_t line_len = len - (p_cur - p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29450 | if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29451 | struct bcode *bcode = ((struct v7_call_frame_bcode *) call_frame)->bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29452 | if (bcode != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29453 | cur_len = printf_stack_line(p_cur, line_len, bcode, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29454 | CALLFRAME_LINENO(call_frame), leading); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29455 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29456 | } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29457 | cur_len = printf_stack_line_cfunc( |
Marko Mikulicic |
0:c0ecb8bf28eb | 29458 | p_cur, line_len, ((struct v7_call_frame_cfunc *) call_frame)->cfunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29459 | leading); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29461 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29462 | total_len += cur_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29463 | if (p_cur != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29464 | p_cur += cur_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29465 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29467 | call_frame = call_frame->prev; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29469 | #if !(V7_ENABLE__StackTrace) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29470 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29471 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29472 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29474 | return total_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29475 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29476 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29478 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29479 | V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29480 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29481 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29482 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29484 | if (v7_is_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29485 | *res = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29486 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29487 | *res = mk_object(v7, v7->vals.error_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29488 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29489 | /* TODO(mkm): set non enumerable but provide toString method */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29490 | v7_set(v7, *res, "message", 7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29492 | #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29493 | /* Save the stack trace */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29494 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29495 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29496 | val_t st_v = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29497 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29498 | v7_own(v7, &st_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29499 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29500 | len = print_stack_trace(NULL, 0, v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29502 | if (len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29503 | /* Now, create a placeholder for string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29504 | st_v = v7_mk_string(v7, NULL, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29505 | len += 1 /*null-term*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29507 | /* And fill it with actual data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29508 | print_stack_trace((char *) v7_get_string(v7, &st_v, NULL), len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29509 | v7->call_stack); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29510 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29511 | v7_set(v7, *res, "stack", ~0, st_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29512 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29513 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29514 | v7_disown(v7, &st_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29516 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29518 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29519 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29521 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29522 | V7_PRIVATE enum v7_err Error_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29523 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29524 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29525 | val_t prefix, msg = v7_get(v7, this_obj, "message", ~0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29526 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29527 | if (!v7_is_string(msg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29528 | *res = v7_mk_string(v7, "Error", ~0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29529 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29530 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29531 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29532 | prefix = v7_mk_string(v7, "Error: ", ~0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29533 | *res = s_concat(v7, prefix, msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29534 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29535 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29536 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29537 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29538 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29539 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29540 | static const char *const error_names[] = {TYPE_ERROR, SYNTAX_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29541 | REFERENCE_ERROR, INTERNAL_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29542 | RANGE_ERROR, EVAL_ERROR}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29544 | V7_STATIC_ASSERT(ARRAY_SIZE(error_names) == ERROR_CTOR_MAX, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29545 | error_name_count_mismatch); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29546 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29547 | V7_PRIVATE void init_error(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29548 | val_t error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29549 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29550 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29551 | error = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29552 | mk_cfunction_obj_with_proto(v7, Error_ctor, 1, v7->vals.error_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29553 | v7_def(v7, v7->vals.global_object, "Error", 5, V7_DESC_ENUMERABLE(0), error); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29554 | set_method(v7, v7->vals.error_prototype, "toString", Error_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29555 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29556 | for (i = 0; i < ARRAY_SIZE(error_names); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29557 | error = mk_cfunction_obj_with_proto( |
Marko Mikulicic |
0:c0ecb8bf28eb | 29558 | v7, Error_ctor, 1, mk_object(v7, v7->vals.error_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29559 | v7_def(v7, v7->vals.global_object, error_names[i], strlen(error_names[i]), |
Marko Mikulicic |
0:c0ecb8bf28eb | 29560 | V7_DESC_ENUMERABLE(0), error); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29561 | v7->vals.error_objects[i] = error; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29562 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29563 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29564 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29565 | #line 1 "v7/src/std_number.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29566 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29567 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29568 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29569 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29570 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29571 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29572 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29573 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29574 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29575 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29576 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29577 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29578 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29579 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29580 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29581 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29582 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29583 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29584 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29586 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29587 | V7_PRIVATE enum v7_err Number_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29588 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29589 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29590 | val_t arg0 = v7_argc(v7) == 0 ? v7_mk_number(v7, 0.0) : v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29591 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29592 | if (v7_is_number(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29593 | *res = arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29594 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29595 | rcode = to_number_v(v7, arg0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29596 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29597 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29598 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29599 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29600 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29601 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29602 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 29603 | get_object_struct(v7->vals.number_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29604 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29605 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29606 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29607 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 29608 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 29609 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29610 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29612 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29613 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29614 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29616 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29617 | V7_PRIVATE enum v7_err n_to_str(struct v7 *v7, const char *format, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29618 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29619 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29620 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29621 | int len, digits = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29622 | char fmt[10], buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29623 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29624 | rcode = to_number_v(v7, arg0, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29625 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29626 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29627 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29628 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29629 | if (v7_get_double(v7, arg0) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29630 | digits = (int) v7_get_double(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29631 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29632 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29633 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29634 | * NOTE: we don't own `arg0` and `this_obj`, since this function is called |
Marko Mikulicic |
0:c0ecb8bf28eb | 29635 | * from cfunctions only, and GC is inhibited during these calls |
Marko Mikulicic |
0:c0ecb8bf28eb | 29636 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29638 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29639 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29640 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29642 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29643 | snprintf(fmt, sizeof(fmt), format, digits); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29644 | len = snprintf(buf, sizeof(buf), fmt, v7_get_double(v7, this_obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29645 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29646 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29648 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29649 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29650 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29651 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29652 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29653 | V7_PRIVATE enum v7_err Number_toFixed(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29654 | return n_to_str(v7, "%%.%dlf", res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29655 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29656 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29657 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29658 | V7_PRIVATE enum v7_err Number_toExp(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29659 | return n_to_str(v7, "%%.%de", res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29660 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29661 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29662 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29663 | V7_PRIVATE enum v7_err Number_toPrecision(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29664 | return Number_toExp(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29665 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29667 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29668 | V7_PRIVATE enum v7_err Number_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29669 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29670 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29671 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29672 | if (!v7_is_number(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29673 | (v7_is_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29674 | v7_get_proto(v7, this_obj) != v7->vals.number_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29675 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29676 | v7_throwf(v7, TYPE_ERROR, "Number.valueOf called on non-number object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29677 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29678 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29680 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29681 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29682 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29683 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29684 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29685 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29686 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29687 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29689 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29690 | * Converts a 64 bit signed integer into a string of a given base. |
Marko Mikulicic |
0:c0ecb8bf28eb | 29691 | * Requires space for 65 bytes (64 bit + null terminator) in the result buffer |
Marko Mikulicic |
0:c0ecb8bf28eb | 29692 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29693 | static char *cs_itoa(int64_t value, char *result, int base) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29694 | char *ptr = result, *ptr1 = result, tmp_char; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29695 | int64_t tmp_value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29696 | int64_t sign = value < 0 ? -1 : 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29697 | const char *base36 = "0123456789abcdefghijklmnopqrstuvwxyz"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29699 | if (base < 2 || base > 36) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29700 | *result = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29701 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29702 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29703 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29704 | /* let's think positive */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29705 | value = value * sign; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29706 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29707 | tmp_value = value; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29708 | value /= base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29709 | *ptr++ = base36[tmp_value - value * base]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29710 | } while (value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29711 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29712 | /* sign */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29713 | if (sign < 0) *ptr++ = '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29714 | *ptr-- = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29715 | while (ptr1 < ptr) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29716 | tmp_char = *ptr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29717 | *ptr-- = *ptr1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29718 | *ptr1++ = tmp_char; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29719 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29720 | return result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29721 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29722 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29723 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29724 | V7_PRIVATE enum v7_err Number_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29725 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29726 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29727 | val_t radixv = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29728 | char buf[65]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29729 | double d, radix; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29730 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29731 | if (this_obj == v7->vals.number_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29732 | *res = v7_mk_string(v7, "0", 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29733 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29734 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29736 | /* Make sure this function was called on Number instance */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29737 | if (!v7_is_number(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29738 | !(v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 29739 | is_prototype_of(v7, this_obj, v7->vals.number_prototype))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29740 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29741 | "Number.toString called on non-number object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29742 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29743 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29744 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29745 | /* Get number primitive */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29746 | rcode = to_number_v(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29747 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29748 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29751 | /* Get radix if provided, or 10 otherwise */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29752 | if (!v7_is_undefined(radixv)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29753 | rcode = to_number_v(v7, radixv, &radixv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29754 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29755 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29756 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29757 | radix = v7_get_double(v7, radixv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29758 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29759 | radix = 10.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29760 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29761 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29762 | d = v7_get_double(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29763 | if (!isnan(d) && (int64_t) d == d && radix >= 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29764 | cs_itoa(d, buf, radix); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29765 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29766 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29767 | rcode = to_string(v7, this_obj, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29768 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29769 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29770 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29771 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29772 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29773 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29774 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29775 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29776 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29777 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29778 | V7_PRIVATE enum v7_err n_isNaN(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29779 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29780 | *res = v7_mk_boolean(v7, !v7_is_number(arg0) || arg0 == V7_TAG_NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29781 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29782 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29783 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29784 | V7_PRIVATE void init_number(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29785 | v7_prop_attr_desc_t attrs_desc = |
Marko Mikulicic |
0:c0ecb8bf28eb | 29786 | (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29787 | val_t num = mk_cfunction_obj_with_proto(v7, Number_ctor, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29788 | v7->vals.number_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29789 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29790 | v7_def(v7, v7->vals.global_object, "Number", 6, V7_DESC_ENUMERABLE(0), num); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29792 | set_cfunc_prop(v7, v7->vals.number_prototype, "toFixed", Number_toFixed); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29793 | set_cfunc_prop(v7, v7->vals.number_prototype, "toPrecision", |
Marko Mikulicic |
0:c0ecb8bf28eb | 29794 | Number_toPrecision); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29795 | set_cfunc_prop(v7, v7->vals.number_prototype, "toExponential", Number_toExp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29796 | set_cfunc_prop(v7, v7->vals.number_prototype, "valueOf", Number_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29797 | set_cfunc_prop(v7, v7->vals.number_prototype, "toString", Number_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29799 | v7_def(v7, num, "MAX_VALUE", 9, attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29800 | v7_mk_number(v7, 1.7976931348623157e+308)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29801 | v7_def(v7, num, "MIN_VALUE", 9, attrs_desc, v7_mk_number(v7, 5e-324)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29802 | #if V7_ENABLE__NUMBER__NEGATIVE_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 29803 | v7_def(v7, num, "NEGATIVE_INFINITY", 17, attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29804 | v7_mk_number(v7, -INFINITY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29805 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29806 | #if V7_ENABLE__NUMBER__POSITIVE_INFINITY |
Marko Mikulicic |
0:c0ecb8bf28eb | 29807 | v7_def(v7, num, "POSITIVE_INFINITY", 17, attrs_desc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29808 | v7_mk_number(v7, INFINITY)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29809 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29810 | v7_def(v7, num, "NaN", 3, attrs_desc, V7_TAG_NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29811 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29812 | v7_def(v7, v7->vals.global_object, "NaN", 3, attrs_desc, V7_TAG_NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29813 | v7_def(v7, v7->vals.global_object, "isNaN", 5, V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 29814 | v7_mk_cfunction(n_isNaN)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29815 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29816 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29817 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29818 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29819 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29820 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29821 | #line 1 "v7/src/std_json.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29822 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29823 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29824 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29825 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29826 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29827 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29828 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29829 | /* Amalgamated: #include "v7/src/stdlib.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29830 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29831 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29832 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29833 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29834 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29835 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29836 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29837 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29838 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29840 | #if defined(V7_ALT_JSON_PARSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29841 | extern enum v7_err v7_alt_json_parse(struct v7 *v7, v7_val_t json_string, |
Marko Mikulicic |
0:c0ecb8bf28eb | 29842 | v7_val_t *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29843 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29844 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29845 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29846 | V7_PRIVATE enum v7_err Json_stringify(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29847 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29848 | char buf[100], *p = v7_to_json(v7, arg0, buf, sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29849 | *res = v7_mk_string(v7, p, strlen(p), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29850 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29851 | if (p != buf) free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29852 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29853 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29855 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29856 | V7_PRIVATE enum v7_err Json_parse(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29857 | v7_val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29858 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29859 | #if defined(V7_ALT_JSON_PARSE) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29860 | rcode = v7_alt_json_parse(v7, arg, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29861 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 29862 | rcode = std_eval(v7, arg, V7_UNDEFINED, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29863 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29864 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29867 | V7_PRIVATE void init_json(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29868 | val_t o = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29869 | set_method(v7, o, "stringify", Json_stringify, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29870 | set_method(v7, o, "parse", Json_parse, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29871 | v7_def(v7, v7->vals.global_object, "JSON", 4, V7_DESC_ENUMERABLE(0), o); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29872 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29873 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29874 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29875 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29876 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29877 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 29878 | #line 1 "v7/src/std_array.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 29879 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 29880 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29881 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 29882 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 29883 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29884 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29885 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29886 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29887 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29888 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29889 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29890 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29891 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29892 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29893 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29894 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29895 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29897 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29898 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29899 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29900 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29901 | struct a_sort_data { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29902 | val_t sort_func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29903 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29904 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29905 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29906 | V7_PRIVATE enum v7_err Array_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29907 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29908 | unsigned long i, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29909 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29910 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29911 | *res = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29912 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29913 | * The interpreter passes dense array to C functions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 29914 | * However dense array implementation is not yet complete |
Marko Mikulicic |
0:c0ecb8bf28eb | 29915 | * so we don't want to propagate them at each call to Array() |
Marko Mikulicic |
0:c0ecb8bf28eb | 29916 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29917 | len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29918 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29919 | rcode = v7_array_set_throwing(v7, *res, i, v7_arg(v7, i), 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 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29926 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29927 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29928 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29929 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29930 | V7_PRIVATE enum v7_err Array_push(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29931 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29932 | int i, len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29934 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29936 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29937 | *res = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29938 | rcode = v7_array_push_throwing(v7, v7_get_this(v7), *res, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29939 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29940 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29942 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29944 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 29945 | * TODO(dfrank) : we need to implement `length` as a real property, and here |
Marko Mikulicic |
0:c0ecb8bf28eb | 29946 | * we need to set new length and return it (even if the object is not an |
Marko Mikulicic |
0:c0ecb8bf28eb | 29947 | * array) |
Marko Mikulicic |
0:c0ecb8bf28eb | 29948 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29950 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 29951 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29952 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29954 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29955 | V7_PRIVATE enum v7_err Array_get_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29956 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29957 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29958 | long len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29960 | if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29961 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29962 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29963 | *res = v7_mk_number(v7, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29964 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29965 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29966 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29967 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29968 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 29969 | V7_PRIVATE enum v7_err Array_set_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29970 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29971 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29972 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29973 | long new_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29975 | rcode = to_long(v7, v7_arg(v7, 0), -1, &new_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29976 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29977 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29978 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 29979 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29980 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29981 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29982 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29983 | } else if (new_len < 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 29984 | (v7_is_number(arg0) && (isnan(v7_get_double(v7, arg0)) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 29985 | isinf(v7_get_double(v7, arg0))))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29986 | rcode = v7_throwf(v7, RANGE_ERROR, "Invalid array length"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29987 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29988 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29989 | struct v7_property **p, **next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29990 | long index, max_index = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29991 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 29992 | /* Remove all items with an index higher than new_len */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 29993 | for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29994 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29995 | const char *s = v7_get_string(v7, &p[0]->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29996 | next = &p[0]->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 29997 | index = strtol(s, NULL, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 29998 | if (index >= new_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 29999 | v7_destroy_property(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30000 | *p = *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30001 | next = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30002 | } else if (index > max_index) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30003 | max_index = index; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30004 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30005 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30007 | /* If we have to expand, insert an item with appropriate index */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30008 | if (new_len > 0 && max_index < new_len - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30009 | char buf[40]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30010 | c_snprintf(buf, sizeof(buf), "%ld", new_len - 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30011 | v7_set(v7, this_obj, buf, strlen(buf), V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30012 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30013 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30014 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30015 | *res = v7_mk_number(v7, new_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30017 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30018 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30019 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30021 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30022 | static enum v7_err a_cmp(struct v7 *v7, void *user_data, const void *pa, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30023 | const void *pb, int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30024 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30025 | struct a_sort_data *sort_data = (struct a_sort_data *) user_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30026 | val_t a = *(val_t *) pa, b = *(val_t *) pb, func = sort_data->sort_func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30027 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30028 | if (v7_is_callable(v7, func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30029 | int saved_inhibit_gc = v7->inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30030 | val_t vres = V7_UNDEFINED, args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30031 | v7_array_push(v7, args, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30032 | v7_array_push(v7, args, b); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30033 | v7->inhibit_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30034 | rcode = b_apply(v7, func, V7_UNDEFINED, args, 0, &vres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30035 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30036 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30038 | v7->inhibit_gc = saved_inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30039 | *res = (int) -v7_get_double(v7, vres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30040 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30041 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30042 | char sa[100], sb[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30043 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30044 | rcode = to_string(v7, a, NULL, sa, sizeof(sa), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30045 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30046 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30047 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30048 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30049 | rcode = to_string(v7, b, NULL, sb, sizeof(sb), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30050 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30051 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30052 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30054 | sa[sizeof(sa) - 1] = sb[sizeof(sb) - 1] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30055 | *res = strcmp(sb, sa); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30056 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30057 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30058 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30059 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30060 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30061 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30062 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30063 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30064 | static enum v7_err a_partition(struct v7 *v7, val_t *a, int l, int r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30065 | void *user_data, int *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30066 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30067 | val_t t, pivot = a[l]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30068 | int i = l, j = r + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30070 | for (;;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30071 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30072 | ++i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30073 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30074 | if (i <= r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30075 | int tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30076 | rcode = a_cmp(v7, user_data, &a[i], &pivot, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30077 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30078 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30079 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30080 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30081 | if (tmp > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30082 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30083 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30084 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30085 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30086 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30087 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30088 | while (1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30089 | int tmp = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30090 | --j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30091 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30092 | rcode = a_cmp(v7, user_data, &a[j], &pivot, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30093 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30094 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30095 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30096 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30097 | if (tmp <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30098 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30099 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30101 | if (i >= j) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30102 | t = a[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30103 | a[i] = a[j]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30104 | a[j] = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30105 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30106 | t = a[l]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30107 | a[l] = a[j]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30108 | a[j] = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30109 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30110 | *res = j; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30111 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30112 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30113 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30115 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30116 | static enum v7_err a_qsort(struct v7 *v7, val_t *a, int l, int r, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30117 | void *user_data) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30118 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30119 | if (l < r) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30120 | int j = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30121 | rcode = a_partition(v7, a, l, r, user_data, &j); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30122 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30123 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30124 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30125 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30126 | rcode = a_qsort(v7, a, l, j - 1, user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30127 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30128 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30129 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30130 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30131 | rcode = a_qsort(v7, a, j + 1, r, user_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30132 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30133 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30134 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30135 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30136 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30137 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30138 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30140 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30141 | static enum v7_err a_sort(struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30142 | enum v7_err (*sorting_func)(struct v7 *v7, void *, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30143 | const void *, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30144 | const void *, int *res), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30145 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30146 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30147 | int i = 0, len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30148 | val_t *arr = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30149 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30151 | *res = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30152 | len = v7_array_length(v7, *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30154 | if (!v7_is_object(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30155 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30156 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30158 | arr = (val_t *) malloc(len * sizeof(arr[0])); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30160 | assert(*res != v7->vals.global_object); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30162 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30163 | arr[i] = v7_array_get(v7, *res, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30164 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30165 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30166 | /* TODO(dfrank): sorting_func isn't actually used! something is wrong here */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30167 | if (sorting_func != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30168 | struct a_sort_data sort_data; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30169 | sort_data.sort_func = arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30170 | rcode = a_qsort(v7, arr, 0, len - 1, &sort_data); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30171 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30172 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30174 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30175 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30176 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30177 | v7_array_set(v7, *res, i, arr[len - (i + 1)]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30178 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30179 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30180 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30181 | if (arr != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30182 | free(arr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30183 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30184 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30185 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30187 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30188 | V7_PRIVATE enum v7_err Array_sort(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30189 | return a_sort(v7, a_cmp, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30190 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30191 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30192 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30193 | V7_PRIVATE enum v7_err Array_reverse(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30194 | return a_sort(v7, NULL, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30195 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30197 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30198 | V7_PRIVATE enum v7_err Array_join(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30199 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30200 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30201 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30202 | size_t sep_size = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30203 | const char *sep = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30204 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30205 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30207 | /* Get pointer to the separator string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30208 | if (!v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30209 | /* If no separator is provided, use comma */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30210 | arg0 = v7_mk_string(v7, ",", 1, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30211 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30212 | sep = v7_get_string(v7, &arg0, &sep_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30213 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30214 | /* Do the actual join */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30215 | if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30216 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30217 | char buf[100], *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30218 | long i, n, num_elems = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30219 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30220 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30222 | for (i = 0; i < num_elems; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30223 | /* Append separator */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30224 | if (i > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30225 | mbuf_append(&m, sep, sep_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30226 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30228 | /* Append next item from an array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30229 | p = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30230 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30231 | size_t tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30232 | rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, buf, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30233 | sizeof(buf), &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30234 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30235 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30236 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30237 | n = tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30238 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30239 | if (n > (long) sizeof(buf)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30240 | p = (char *) malloc(n + 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30241 | rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, p, n, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30242 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30243 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30244 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30245 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30246 | mbuf_append(&m, p, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30247 | if (p != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30248 | free(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30251 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30252 | /* mbuf contains concatenated string now. Copy it to the result. */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30253 | *res = v7_mk_string(v7, m.buf, m.len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30254 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30255 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30256 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30257 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30258 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30259 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30260 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30261 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30262 | V7_PRIVATE enum v7_err Array_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30263 | return Array_join(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30264 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30265 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30266 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30267 | static enum v7_err a_splice(struct v7 *v7, int mutate, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30268 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30269 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30270 | long i, len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30271 | long num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30272 | long elems_to_insert = num_args > 2 ? num_args - 2 : 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30273 | long arg0, arg1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30274 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30275 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30276 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30277 | "Array.splice or Array.slice called on non-object value"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30278 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30279 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30280 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30281 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30282 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30283 | rcode = to_long(v7, v7_arg(v7, 0), 0, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30284 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30285 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30286 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30287 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30288 | rcode = to_long(v7, v7_arg(v7, 1), len, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30289 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30290 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30291 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30292 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30293 | /* Bounds check */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30294 | if (!mutate && len <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30295 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30296 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30297 | if (arg0 < 0) arg0 = len + arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30298 | if (arg0 < 0) arg0 = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30299 | if (arg0 > len) arg0 = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30300 | if (mutate) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30301 | if (arg1 < 0) arg1 = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30302 | arg1 += arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30303 | } else if (arg1 < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30304 | arg1 = len + arg1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30305 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30307 | /* Create return value - slice */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30308 | for (i = arg0; i < arg1 && i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30309 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 30310 | v7_array_push_throwing(v7, *res, v7_array_get(v7, this_obj, i), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30311 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30312 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30313 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30314 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30315 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30316 | if (mutate && get_object_struct(this_obj)->attributes & V7_OBJ_DENSE_ARRAY) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30317 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30318 | * dense arrays are spliced by memmoving leaving the trailing |
Marko Mikulicic |
0:c0ecb8bf28eb | 30319 | * space allocated for future appends. |
Marko Mikulicic |
0:c0ecb8bf28eb | 30320 | * TODO(mkm): figure out if trimming is better |
Marko Mikulicic |
0:c0ecb8bf28eb | 30321 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30322 | struct v7_property *p = |
Marko Mikulicic |
0:c0ecb8bf28eb | 30323 | v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30324 | struct mbuf *abuf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30325 | if (p == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30326 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30327 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30328 | abuf = (struct mbuf *) v7_get_ptr(v7, p->value); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30329 | if (abuf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30330 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30331 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30333 | memmove(abuf->buf + arg0 * sizeof(val_t), abuf->buf + arg1 * sizeof(val_t), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30334 | (len - arg1) * sizeof(val_t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30335 | abuf->len -= (arg1 - arg0) * sizeof(val_t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30336 | } else if (mutate) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30337 | /* If splicing, modify this_obj array: remove spliced sub-array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30338 | struct v7_property **p, **next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30339 | long i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30340 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30341 | for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30342 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30343 | const char *s = v7_get_string(v7, &p[0]->name, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30344 | next = &p[0]->next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30345 | i = strtol(s, NULL, 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30346 | if (i >= arg0 && i < arg1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30347 | /* Remove items from spliced sub-array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30348 | v7_destroy_property(p); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30349 | *p = *next; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30350 | next = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30351 | } else if (i >= arg1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30352 | /* Modify indices of the elements past sub-array */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30353 | char key[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30354 | size_t n = c_snprintf(key, sizeof(key), "%ld", |
Marko Mikulicic |
0:c0ecb8bf28eb | 30355 | i - (arg1 - arg0) + elems_to_insert); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30356 | p[0]->name = v7_mk_string(v7, key, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30357 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30358 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30359 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30360 | /* Insert optional extra elements */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30361 | for (i = 2; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30362 | char key[20]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30363 | size_t n = c_snprintf(key, sizeof(key), "%ld", arg0 + i - 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30364 | rcode = set_property(v7, this_obj, key, n, v7_arg(v7, i), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30365 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30366 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30367 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30368 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30369 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30371 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30372 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30373 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30375 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30376 | V7_PRIVATE enum v7_err Array_slice(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30377 | return a_splice(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30378 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30380 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30381 | V7_PRIVATE enum v7_err Array_splice(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30382 | return a_splice(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30383 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30385 | static void a_prep1(struct v7 *v7, val_t t, val_t *a0, val_t *a1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30386 | *a0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30387 | *a1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30388 | if (v7_is_undefined(*a1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30389 | *a1 = t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30390 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30391 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30393 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30394 | * Call callback function `cb`, passing `this_obj` as `this`, with the |
Marko Mikulicic |
0:c0ecb8bf28eb | 30395 | * following arguments: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30396 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 30397 | * cb(v, n, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30398 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 30399 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30400 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30401 | static enum v7_err a_prep2(struct v7 *v7, val_t cb, val_t v, val_t n, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30402 | val_t this_obj, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30403 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30404 | int saved_inhibit_gc = v7->inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30405 | val_t args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30406 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30407 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30409 | v7_own(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30410 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30411 | v7_array_push(v7, args, v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30412 | v7_array_push(v7, args, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30413 | v7_array_push(v7, args, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30415 | v7->inhibit_gc = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30416 | rcode = b_apply(v7, cb, this_obj, args, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30417 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30418 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30419 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30420 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30421 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30422 | v7->inhibit_gc = saved_inhibit_gc; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30423 | v7_disown(v7, &args); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30424 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30425 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30426 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30427 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30428 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30429 | V7_PRIVATE enum v7_err Array_forEach(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30430 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30431 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30432 | val_t v = V7_UNDEFINED, cb = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30433 | unsigned long len, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30434 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30435 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30436 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30437 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30438 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30439 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30440 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30443 | if (!v7_is_callable(v7, cb)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30444 | rcode = v7_throwf(v7, TYPE_ERROR, "Function expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30445 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30447 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30448 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30450 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30451 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30452 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30453 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30455 | rcode = a_prep2(v7, cb, v, v7_mk_number(v7, i), this_obj, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30456 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30457 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30458 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30459 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30461 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30462 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30463 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30464 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30465 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30466 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30467 | V7_PRIVATE enum v7_err Array_map(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30468 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30469 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30470 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30471 | unsigned long len, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30472 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30473 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30474 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30475 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30476 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30477 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30478 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30479 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30480 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30481 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30482 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30483 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30484 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30485 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30486 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30487 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30488 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30489 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30490 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30491 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30492 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30493 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30494 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30495 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30496 | rcode = v7_array_set_throwing(v7, *res, i, el, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30497 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30498 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30499 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30500 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30501 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30502 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30503 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30504 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30505 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30506 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30507 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30508 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30509 | V7_PRIVATE enum v7_err Array_every(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30510 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30511 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30512 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30513 | unsigned long i, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30514 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30515 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30516 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30518 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30519 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30520 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30521 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30522 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30523 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30524 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30525 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30526 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30527 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30528 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30529 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30530 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30531 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30532 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30533 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30534 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30535 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30536 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30537 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30538 | if (!v7_is_truthy(v7, el)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30539 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30540 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30541 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30544 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30545 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30546 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30547 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30548 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30549 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30550 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30552 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30553 | V7_PRIVATE enum v7_err Array_some(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30554 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30555 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30556 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30557 | unsigned long i, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30558 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30559 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30560 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30561 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30562 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30563 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30564 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30565 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30566 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30567 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30568 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30570 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30571 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30572 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30573 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30574 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30575 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30576 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30577 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30578 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30579 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30580 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30581 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30582 | if (v7_is_truthy(v7, el)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30583 | *res = v7_mk_boolean(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30584 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30585 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30586 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30587 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30588 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30589 | *res = v7_mk_boolean(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30591 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30592 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30593 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30594 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30595 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30596 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30597 | V7_PRIVATE enum v7_err Array_filter(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30598 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30599 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30600 | val_t arg0, arg1, el, v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30601 | unsigned long len, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30602 | int has; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30603 | /* a_prep2 uninhibits GC when calling cb */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30604 | struct gc_tmp_frame vf = new_tmp_frame(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30605 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30606 | if (!v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30607 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30608 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30609 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30610 | a_prep1(v7, this_obj, &arg0, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30611 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30612 | len = v7_array_length(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30614 | tmp_stack_push(&vf, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30615 | tmp_stack_push(&vf, &arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30616 | tmp_stack_push(&vf, &v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30617 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30618 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30619 | v = v7_array_get2(v7, this_obj, i, &has); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30620 | if (!has) continue; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30621 | rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30622 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30623 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30624 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30625 | if (v7_is_truthy(v7, el)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30626 | rcode = v7_array_push_throwing(v7, *res, v, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30627 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30628 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30629 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30630 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30631 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30634 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30635 | tmp_frame_cleanup(&vf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30636 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30637 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30638 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30639 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30640 | V7_PRIVATE enum v7_err Array_concat(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30641 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30642 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30643 | size_t i, j, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30644 | val_t saved_args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30645 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30646 | if (!v7_is_array(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30647 | rcode = v7_throwf(v7, TYPE_ERROR, "Array expected"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30648 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30649 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30651 | len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30652 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30653 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30654 | * reuse a_splice but override it's arguments. a_splice |
Marko Mikulicic |
0:c0ecb8bf28eb | 30655 | * internally uses a lot of helpers that fetch arguments |
Marko Mikulicic |
0:c0ecb8bf28eb | 30656 | * from the v7 context. |
Marko Mikulicic |
0:c0ecb8bf28eb | 30657 | * TODO(mkm): we need a better helper call another cfunction |
Marko Mikulicic |
0:c0ecb8bf28eb | 30658 | * from a cfunction. |
Marko Mikulicic |
0:c0ecb8bf28eb | 30659 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30660 | saved_args = v7->vals.arguments; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30661 | v7->vals.arguments = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30662 | rcode = a_splice(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30663 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30664 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30665 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30666 | v7->vals.arguments = saved_args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30667 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30668 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30669 | val_t a = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30670 | if (!v7_is_array(v7, a)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30671 | rcode = v7_array_push_throwing(v7, *res, a, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30672 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30673 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30674 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30675 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30676 | size_t alen = v7_array_length(v7, a); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30677 | for (j = 0; j < alen; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30678 | rcode = v7_array_push_throwing(v7, *res, v7_array_get(v7, a, j), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30679 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30680 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30681 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30682 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30683 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30685 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30686 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30687 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30688 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30690 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30691 | V7_PRIVATE enum v7_err Array_isArray(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30692 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30693 | *res = v7_mk_boolean(v7, v7_is_array(v7, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30694 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30695 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30696 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30697 | V7_PRIVATE void init_array(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30698 | val_t ctor = mk_cfunction_obj(v7, Array_ctor, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30699 | val_t length = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30701 | v7_set(v7, ctor, "prototype", 9, v7->vals.array_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30702 | set_method(v7, ctor, "isArray", Array_isArray, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30703 | v7_set(v7, v7->vals.global_object, "Array", 5, ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30704 | v7_def(v7, v7->vals.array_prototype, "constructor", ~0, _V7_DESC_HIDDEN(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30705 | ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30706 | v7_set(v7, ctor, "name", 4, v7_mk_string(v7, "Array", ~0, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30708 | set_method(v7, v7->vals.array_prototype, "concat", Array_concat, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30709 | set_method(v7, v7->vals.array_prototype, "every", Array_every, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30710 | set_method(v7, v7->vals.array_prototype, "filter", Array_filter, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30711 | set_method(v7, v7->vals.array_prototype, "forEach", Array_forEach, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30712 | set_method(v7, v7->vals.array_prototype, "join", Array_join, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30713 | set_method(v7, v7->vals.array_prototype, "map", Array_map, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30714 | set_method(v7, v7->vals.array_prototype, "push", Array_push, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30715 | set_method(v7, v7->vals.array_prototype, "reverse", Array_reverse, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30716 | set_method(v7, v7->vals.array_prototype, "slice", Array_slice, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30717 | set_method(v7, v7->vals.array_prototype, "some", Array_some, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30718 | set_method(v7, v7->vals.array_prototype, "sort", Array_sort, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30719 | set_method(v7, v7->vals.array_prototype, "splice", Array_splice, 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30720 | set_method(v7, v7->vals.array_prototype, "toString", Array_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30721 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30722 | v7_array_set(v7, length, 0, v7_mk_cfunction(Array_get_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30723 | v7_array_set(v7, length, 1, v7_mk_cfunction(Array_set_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30724 | v7_def(v7, v7->vals.array_prototype, "length", 6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30725 | V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1) | V7_DESC_SETTER(1), length); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30726 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30727 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30728 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30729 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30730 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30731 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 30732 | #line 1 "v7/src/std_boolean.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 30733 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30734 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30735 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 30736 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 30737 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30738 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30739 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30740 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30741 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30742 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30743 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30744 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30745 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30746 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30747 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30749 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30750 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30751 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30753 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30754 | V7_PRIVATE enum v7_err Boolean_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30755 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30756 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30758 | *res = to_boolean_v(v7, v7_arg(v7, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30760 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30761 | /* called as "new Boolean(...)" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30762 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30763 | get_object_struct(v7->vals.boolean_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30764 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30765 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30766 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30767 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 30768 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 30769 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30770 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30771 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30772 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30773 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30775 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30776 | V7_PRIVATE enum v7_err Boolean_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30777 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30778 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30779 | if (!v7_is_boolean(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30780 | (v7_is_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30781 | v7_get_proto(v7, this_obj) != v7->vals.boolean_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30782 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30783 | "Boolean.valueOf called on non-boolean object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30784 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30786 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30787 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30788 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30789 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30790 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30791 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30792 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30793 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30794 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30795 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30796 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30797 | V7_PRIVATE enum v7_err Boolean_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30798 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30799 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30800 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30801 | *res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30802 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30803 | if (this_obj == v7->vals.boolean_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30804 | *res = v7_mk_string(v7, "false", 5, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30805 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30806 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30807 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30808 | if (!v7_is_boolean(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30809 | !(v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 30810 | is_prototype_of(v7, this_obj, v7->vals.boolean_prototype))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30811 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30812 | "Boolean.toString called on non-boolean object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30813 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30814 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30815 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30816 | rcode = obj_value_of(v7, this_obj, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30817 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30818 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30819 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30821 | rcode = primitive_to_str(v7, *res, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30822 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30823 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30824 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30825 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30826 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30827 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30828 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30830 | V7_PRIVATE void init_boolean(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30831 | val_t ctor = mk_cfunction_obj_with_proto(v7, Boolean_ctor, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 30832 | v7->vals.boolean_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30833 | v7_set(v7, v7->vals.global_object, "Boolean", 7, ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30835 | set_cfunc_prop(v7, v7->vals.boolean_prototype, "valueOf", Boolean_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30836 | set_cfunc_prop(v7, v7->vals.boolean_prototype, "toString", Boolean_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30837 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30838 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30839 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30840 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30841 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30842 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 30843 | #line 1 "v7/src/std_math.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 30844 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30845 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 30846 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 30847 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 30848 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30850 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30851 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30852 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30853 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30854 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30855 | #if V7_ENABLE__Math |
Marko Mikulicic |
0:c0ecb8bf28eb | 30856 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30857 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30858 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30859 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30861 | #ifdef __WATCOM__ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30862 | int matherr(struct _exception *exc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30863 | if (exc->type == DOMAIN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30864 | exc->retval = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30865 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30866 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30867 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30868 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30869 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30870 | #if V7_ENABLE__Math__abs || V7_ENABLE__Math__acos || V7_ENABLE__Math__asin || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30871 | V7_ENABLE__Math__atan || V7_ENABLE__Math__ceil || V7_ENABLE__Math__cos || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30872 | V7_ENABLE__Math__exp || V7_ENABLE__Math__floor || V7_ENABLE__Math__log || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30873 | V7_ENABLE__Math__round || V7_ENABLE__Math__sin || V7_ENABLE__Math__sqrt || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30874 | V7_ENABLE__Math__tan |
Marko Mikulicic |
0:c0ecb8bf28eb | 30875 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30876 | static enum v7_err m_one_arg(struct v7 *v7, double (*f)(double), val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30877 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30878 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30879 | double d0 = v7_get_double(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30880 | #ifdef V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 30881 | if (isnan(d0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30882 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30883 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30884 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30885 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30886 | *res = v7_mk_number(v7, f(d0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30887 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30888 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30889 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30890 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30892 | #endif /* V7_ENABLE__Math__* */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30894 | #if V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 30895 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30896 | static enum v7_err m_two_arg(struct v7 *v7, double (*f)(double, double), |
Marko Mikulicic |
0:c0ecb8bf28eb | 30897 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30898 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30899 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30900 | val_t arg1 = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30901 | double d0 = v7_get_double(v7, arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30902 | double d1 = v7_get_double(v7, arg1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30903 | #ifdef V7_BROKEN_NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 30904 | /* pow(NaN,0) == 1, doesn't fix atan2, but who cares */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30905 | if (isnan(d1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30906 | *res = V7_TAG_NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30907 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30908 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30909 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30910 | *res = v7_mk_number(v7, f(d0, d1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30911 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30913 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 30914 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30916 | #endif /* V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30918 | #define DEFINE_WRAPPER(name, func) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30919 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30920 | V7_PRIVATE enum v7_err Math_##name(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30921 | return func(v7, name, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30922 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30923 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30924 | /* Visual studio 2012+ has round() */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30925 | #if V7_ENABLE__Math__round && \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30926 | ((defined(V7_WINDOWS) && _MSC_VER < 1700) || defined(__WATCOM__)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30927 | static double round(double n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30928 | return n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30929 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30930 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30931 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30932 | #if V7_ENABLE__Math__abs |
Marko Mikulicic |
0:c0ecb8bf28eb | 30933 | DEFINE_WRAPPER(fabs, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30934 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30935 | #if V7_ENABLE__Math__acos |
Marko Mikulicic |
0:c0ecb8bf28eb | 30936 | DEFINE_WRAPPER(acos, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30937 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30938 | #if V7_ENABLE__Math__asin |
Marko Mikulicic |
0:c0ecb8bf28eb | 30939 | DEFINE_WRAPPER(asin, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30940 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30941 | #if V7_ENABLE__Math__atan |
Marko Mikulicic |
0:c0ecb8bf28eb | 30942 | DEFINE_WRAPPER(atan, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30943 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30944 | #if V7_ENABLE__Math__atan2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 30945 | DEFINE_WRAPPER(atan2, m_two_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30946 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30947 | #if V7_ENABLE__Math__ceil |
Marko Mikulicic |
0:c0ecb8bf28eb | 30948 | DEFINE_WRAPPER(ceil, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30949 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30950 | #if V7_ENABLE__Math__cos |
Marko Mikulicic |
0:c0ecb8bf28eb | 30951 | DEFINE_WRAPPER(cos, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30952 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30953 | #if V7_ENABLE__Math__exp |
Marko Mikulicic |
0:c0ecb8bf28eb | 30954 | DEFINE_WRAPPER(exp, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30955 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30956 | #if V7_ENABLE__Math__floor |
Marko Mikulicic |
0:c0ecb8bf28eb | 30957 | DEFINE_WRAPPER(floor, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30958 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30959 | #if V7_ENABLE__Math__log |
Marko Mikulicic |
0:c0ecb8bf28eb | 30960 | DEFINE_WRAPPER(log, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30961 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30962 | #if V7_ENABLE__Math__pow |
Marko Mikulicic |
0:c0ecb8bf28eb | 30963 | DEFINE_WRAPPER(pow, m_two_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30964 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30965 | #if V7_ENABLE__Math__round |
Marko Mikulicic |
0:c0ecb8bf28eb | 30966 | DEFINE_WRAPPER(round, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30967 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30968 | #if V7_ENABLE__Math__sin |
Marko Mikulicic |
0:c0ecb8bf28eb | 30969 | DEFINE_WRAPPER(sin, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30970 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30971 | #if V7_ENABLE__Math__sqrt |
Marko Mikulicic |
0:c0ecb8bf28eb | 30972 | DEFINE_WRAPPER(sqrt, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30973 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30974 | #if V7_ENABLE__Math__tan |
Marko Mikulicic |
0:c0ecb8bf28eb | 30975 | DEFINE_WRAPPER(tan, m_one_arg) |
Marko Mikulicic |
0:c0ecb8bf28eb | 30976 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 30977 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30978 | #if V7_ENABLE__Math__random |
Marko Mikulicic |
0:c0ecb8bf28eb | 30979 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30980 | V7_PRIVATE enum v7_err Math_random(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30981 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30982 | *res = v7_mk_number(v7, (double) rand() / RAND_MAX); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30983 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30984 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30985 | #endif /* V7_ENABLE__Math__random */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 30986 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30987 | #if V7_ENABLE__Math__min || V7_ENABLE__Math__max |
Marko Mikulicic |
0:c0ecb8bf28eb | 30988 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 30989 | static enum v7_err min_max(struct v7 *v7, int is_min, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30990 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30991 | double dres = NAN; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30992 | int i, len = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 30994 | for (i = 0; i < len; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30995 | double v = v7_get_double(v7, v7_arg(v7, i)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 30996 | if (isnan(dres) || (is_min && v < dres) || (!is_min && v > dres)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 30997 | dres = v; |
Marko Mikulicic |
0:c0ecb8bf28eb | 30998 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 30999 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31000 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31001 | *res = v7_mk_number(v7, dres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31002 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31003 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31004 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31005 | #endif /* V7_ENABLE__Math__min || V7_ENABLE__Math__max */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31007 | #if V7_ENABLE__Math__min |
Marko Mikulicic |
0:c0ecb8bf28eb | 31008 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31009 | V7_PRIVATE enum v7_err Math_min(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31010 | return min_max(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31011 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31012 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31013 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31014 | #if V7_ENABLE__Math__max |
Marko Mikulicic |
0:c0ecb8bf28eb | 31015 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31016 | V7_PRIVATE enum v7_err Math_max(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31017 | return min_max(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31018 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31019 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31020 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31021 | V7_PRIVATE void init_math(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31022 | val_t math = v7_mk_object(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31024 | #if V7_ENABLE__Math__abs |
Marko Mikulicic |
0:c0ecb8bf28eb | 31025 | set_cfunc_prop(v7, math, "abs", Math_fabs); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31026 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31027 | #if V7_ENABLE__Math__acos |
Marko Mikulicic |
0:c0ecb8bf28eb | 31028 | set_cfunc_prop(v7, math, "acos", Math_acos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31029 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31030 | #if V7_ENABLE__Math__asin |
Marko Mikulicic |
0:c0ecb8bf28eb | 31031 | set_cfunc_prop(v7, math, "asin", Math_asin); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31032 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31033 | #if V7_ENABLE__Math__atan |
Marko Mikulicic |
0:c0ecb8bf28eb | 31034 | set_cfunc_prop(v7, math, "atan", Math_atan); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31035 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31036 | #if V7_ENABLE__Math__atan2 |
Marko Mikulicic |
0:c0ecb8bf28eb | 31037 | set_cfunc_prop(v7, math, "atan2", Math_atan2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31038 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31039 | #if V7_ENABLE__Math__ceil |
Marko Mikulicic |
0:c0ecb8bf28eb | 31040 | set_cfunc_prop(v7, math, "ceil", Math_ceil); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31041 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31042 | #if V7_ENABLE__Math__cos |
Marko Mikulicic |
0:c0ecb8bf28eb | 31043 | set_cfunc_prop(v7, math, "cos", Math_cos); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31044 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31045 | #if V7_ENABLE__Math__exp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31046 | set_cfunc_prop(v7, math, "exp", Math_exp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31047 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31048 | #if V7_ENABLE__Math__floor |
Marko Mikulicic |
0:c0ecb8bf28eb | 31049 | set_cfunc_prop(v7, math, "floor", Math_floor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31050 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31051 | #if V7_ENABLE__Math__log |
Marko Mikulicic |
0:c0ecb8bf28eb | 31052 | set_cfunc_prop(v7, math, "log", Math_log); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31053 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31054 | #if V7_ENABLE__Math__max |
Marko Mikulicic |
0:c0ecb8bf28eb | 31055 | set_cfunc_prop(v7, math, "max", Math_max); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31056 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31057 | #if V7_ENABLE__Math__min |
Marko Mikulicic |
0:c0ecb8bf28eb | 31058 | set_cfunc_prop(v7, math, "min", Math_min); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31059 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31060 | #if V7_ENABLE__Math__pow |
Marko Mikulicic |
0:c0ecb8bf28eb | 31061 | set_cfunc_prop(v7, math, "pow", Math_pow); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31062 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31063 | #if V7_ENABLE__Math__random |
Marko Mikulicic |
0:c0ecb8bf28eb | 31064 | /* Incorporate our pointer into the RNG. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31065 | * If srand() has not been called before, this will provide some randomness. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31066 | * If it has, it will hopefully not make things worse. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31067 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31068 | srand(rand() ^ ((uintptr_t) v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31069 | set_cfunc_prop(v7, math, "random", Math_random); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31070 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31071 | #if V7_ENABLE__Math__round |
Marko Mikulicic |
0:c0ecb8bf28eb | 31072 | set_cfunc_prop(v7, math, "round", Math_round); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31073 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31074 | #if V7_ENABLE__Math__sin |
Marko Mikulicic |
0:c0ecb8bf28eb | 31075 | set_cfunc_prop(v7, math, "sin", Math_sin); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31076 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31077 | #if V7_ENABLE__Math__sqrt |
Marko Mikulicic |
0:c0ecb8bf28eb | 31078 | set_cfunc_prop(v7, math, "sqrt", Math_sqrt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31079 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31080 | #if V7_ENABLE__Math__tan |
Marko Mikulicic |
0:c0ecb8bf28eb | 31081 | set_cfunc_prop(v7, math, "tan", Math_tan); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31082 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31084 | #if V7_ENABLE__Math__constants |
Marko Mikulicic |
0:c0ecb8bf28eb | 31085 | v7_set(v7, math, "E", 1, v7_mk_number(v7, M_E)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31086 | v7_set(v7, math, "PI", 2, v7_mk_number(v7, M_PI)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31087 | v7_set(v7, math, "LN2", 3, v7_mk_number(v7, M_LN2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31088 | v7_set(v7, math, "LN10", 4, v7_mk_number(v7, M_LN10)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31089 | v7_set(v7, math, "LOG2E", 5, v7_mk_number(v7, M_LOG2E)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31090 | v7_set(v7, math, "LOG10E", 6, v7_mk_number(v7, M_LOG10E)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31091 | v7_set(v7, math, "SQRT1_2", 7, v7_mk_number(v7, M_SQRT1_2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31092 | v7_set(v7, math, "SQRT2", 5, v7_mk_number(v7, M_SQRT2)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31093 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31095 | v7_set(v7, v7->vals.global_object, "Math", 4, math); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31096 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31098 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31099 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31100 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31102 | #endif /* V7_ENABLE__Math */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31103 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 31104 | #line 1 "v7/src/std_string.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 31105 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31106 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31107 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 31108 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 31109 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31110 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31111 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31112 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31113 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31114 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31115 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31116 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31117 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31118 | /* Amalgamated: #include "v7/src/std_regex.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31119 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31120 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31121 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31122 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31123 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31124 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31125 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31126 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31127 | /* Substring implementations: RegExp-based and String-based {{{ */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31128 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31129 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31130 | * Substring context: currently, used in Str_split() only, but will probably |
Marko Mikulicic |
0:c0ecb8bf28eb | 31131 | * be used in Str_replace() and other functions as well. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31132 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 31133 | * Needed to provide different implementation for RegExp or String arguments, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31134 | * keeping common parts reusable. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31135 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31136 | struct _str_split_ctx { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31137 | /* implementation-specific data */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31138 | union { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31139 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31140 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31141 | struct slre_prog *prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31142 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31143 | } regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31144 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31145 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31146 | struct { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31147 | val_t sep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31148 | } string; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31149 | } impl; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31151 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31153 | /* start and end of previous match (set by `p_exec()`) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31154 | const char *match_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31155 | const char *match_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31157 | /* pointers to implementation functions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31158 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31159 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31160 | * Initialize context |
Marko Mikulicic |
0:c0ecb8bf28eb | 31161 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31162 | void (*p_init)(struct _str_split_ctx *ctx, struct v7 *v7, val_t sep); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31163 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31164 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31165 | * Look for the next match, set `match_start` and `match_end` to appropriate |
Marko Mikulicic |
0:c0ecb8bf28eb | 31166 | * values. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31167 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 31168 | * Returns 0 if match found, 1 otherwise (in accordance with `slre_exec()`) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31169 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31170 | int (*p_exec)(struct _str_split_ctx *ctx, const char *start, const char *end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31172 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31173 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31174 | * Add captured data to resulting array (for RegExp-based implementation only) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31175 | * |
Marko Mikulicic |
0:c0ecb8bf28eb | 31176 | * Returns updated `elem` value |
Marko Mikulicic |
0:c0ecb8bf28eb | 31177 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31178 | long (*p_add_caps)(struct _str_split_ctx *ctx, val_t res, long elem, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31179 | long limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31180 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31181 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31182 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31183 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31184 | /* RegExp-based implementation of `p_init` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31185 | static void subs_regexp_init(struct _str_split_ctx *ctx, struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31186 | val_t sep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31187 | ctx->v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31188 | ctx->impl.regexp.prog = v7_get_regexp_struct(v7, sep)->compiled_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31189 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31191 | /* RegExp-based implementation of `p_exec` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31192 | static int subs_regexp_exec(struct _str_split_ctx *ctx, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31193 | const char *end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31194 | int ret = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31195 | slre_exec(ctx->impl.regexp.prog, 0, start, end, &ctx->impl.regexp.loot); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31196 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31197 | ctx->match_start = ctx->impl.regexp.loot.caps[0].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31198 | ctx->match_end = ctx->impl.regexp.loot.caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31199 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31200 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31203 | /* RegExp-based implementation of `p_add_caps` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31204 | static long subs_regexp_split_add_caps(struct _str_split_ctx *ctx, val_t res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31205 | long elem, long limit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31206 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31207 | for (i = 1; i < ctx->impl.regexp.loot.num_captures && elem < limit; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31208 | size_t cap_len = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31209 | ctx->impl.regexp.loot.caps[i].end - ctx->impl.regexp.loot.caps[i].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31210 | v7_array_push( |
Marko Mikulicic |
0:c0ecb8bf28eb | 31211 | ctx->v7, res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31212 | (ctx->impl.regexp.loot.caps[i].start != NULL) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31213 | ? v7_mk_string(ctx->v7, ctx->impl.regexp.loot.caps[i].start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31214 | cap_len, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31215 | : V7_UNDEFINED); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31216 | elem++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31217 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31218 | return elem; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31219 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31220 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31222 | /* String-based implementation of `p_init` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31223 | static void subs_string_init(struct _str_split_ctx *ctx, struct v7 *v7, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31224 | val_t sep) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31225 | ctx->v7 = v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31226 | ctx->impl.string.sep = sep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31227 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31228 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31229 | /* String-based implementation of `p_exec` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31230 | static int subs_string_exec(struct _str_split_ctx *ctx, const char *start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31231 | const char *end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31232 | int ret = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31233 | size_t sep_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31234 | const char *psep = v7_get_string(ctx->v7, &ctx->impl.string.sep, &sep_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31235 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31236 | if (sep_len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31237 | /* separator is an empty string: match empty string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31238 | ctx->match_start = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31239 | ctx->match_end = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31240 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31241 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31242 | size_t i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31243 | for (i = 0; start <= (end - sep_len); ++i, start = utfnshift(start, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31244 | if (memcmp(start, psep, sep_len) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31245 | ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31246 | ctx->match_start = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31247 | ctx->match_end = start + sep_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31248 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31249 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31250 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31251 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31253 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31254 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31256 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31257 | /* String-based implementation of `p_add_caps` in `struct _str_split_ctx` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31258 | static long subs_string_split_add_caps(struct _str_split_ctx *ctx, val_t res, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31259 | long elem, long limit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31260 | /* this is a stub function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31261 | (void) ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31262 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31263 | (void) limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31264 | return elem; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31265 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31266 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31268 | /* }}} */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31270 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31271 | V7_PRIVATE enum v7_err String_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31272 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31273 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31274 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31275 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31276 | *res = arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31277 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31278 | if (v7_argc(v7) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31279 | *res = v7_mk_string(v7, NULL, 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31280 | } else if (!v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31281 | rcode = to_string(v7, arg0, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31282 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31283 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31284 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31285 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31286 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31287 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31288 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31289 | get_object_struct(v7->vals.string_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31290 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31291 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31292 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 31293 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 31294 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31295 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31296 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31297 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31298 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31299 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31301 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31302 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31303 | V7_PRIVATE enum v7_err Str_fromCharCode(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31304 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31305 | int i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31307 | *res = v7_mk_string(v7, "", 0, 1); /* Empty string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31309 | for (i = 0; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31310 | char buf[10]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31311 | val_t arg = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31312 | double d = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31313 | Rune r = (Rune)((int32_t)(isnan(d) || isinf(d) ? 0 : d) & 0xffff); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31314 | int n = runetochar(buf, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31315 | val_t s = v7_mk_string(v7, buf, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31316 | *res = s_concat(v7, *res, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31317 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31318 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31319 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31320 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31321 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31322 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31323 | static enum v7_err s_charCodeAt(struct v7 *v7, double *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31324 | return v7_char_code_at(v7, v7_get_this(v7), v7_arg(v7, 0), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31325 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31327 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31328 | V7_PRIVATE enum v7_err Str_charCodeAt(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31329 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31330 | double dnum = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31331 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31332 | rcode = s_charCodeAt(v7, &dnum); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31333 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31334 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31335 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31336 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31337 | *res = v7_mk_number(v7, dnum); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31338 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31339 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31340 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31343 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31344 | V7_PRIVATE enum v7_err Str_charAt(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31345 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31346 | double code = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31347 | char buf[10] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31348 | int len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31350 | rcode = s_charCodeAt(v7, &code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31351 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31352 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31353 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31354 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31355 | if (!isnan(code)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31356 | Rune r = (Rune) code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31357 | len = runetochar(buf, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31358 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31359 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31361 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31362 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31365 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31366 | V7_PRIVATE enum v7_err Str_concat(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31367 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31368 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31369 | int i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31370 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31371 | rcode = to_string(v7, this_obj, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31372 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31373 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31374 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31375 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31376 | for (i = 0; i < num_args; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31377 | val_t str = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31378 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31379 | rcode = to_string(v7, v7_arg(v7, i), &str, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31380 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31381 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31382 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31383 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31384 | *res = s_concat(v7, *res, str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31385 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31386 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31387 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31388 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31389 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31390 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31391 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31392 | static enum v7_err s_index_of(struct v7 *v7, int last, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31393 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31394 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31395 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31396 | size_t fromIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31397 | double dres = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31398 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31399 | if (!v7_is_undefined(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31400 | const char *p1, *p2, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31401 | size_t i, len1, len2, bytecnt1, bytecnt2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31402 | val_t sub = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31403 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31404 | rcode = to_string(v7, arg0, &sub, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31405 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31406 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31407 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31408 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31409 | rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31410 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31411 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31412 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31413 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31414 | p1 = v7_get_string(v7, &this_obj, &bytecnt1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31415 | p2 = v7_get_string(v7, &sub, &bytecnt2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31416 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31417 | if (bytecnt2 <= bytecnt1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31418 | end = p1 + bytecnt1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31419 | len1 = utfnlen(p1, bytecnt1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31420 | len2 = utfnlen(p2, bytecnt2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31421 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31422 | if (v7_argc(v7) > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31423 | /* `fromIndex` was provided. Normalize it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31424 | double d = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31425 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31426 | val_t arg = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31427 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31428 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31429 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31430 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31431 | d = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31432 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31433 | if (isnan(d) || d < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31434 | d = 0.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31435 | } else if (isinf(d) || d > len1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31436 | d = len1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31437 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31438 | fromIndex = d; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31439 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31440 | /* adjust pointers accordingly to `fromIndex` */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31441 | if (last) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31442 | const char *end_tmp = utfnshift(p1, fromIndex + len2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31443 | end = (end_tmp < end) ? end_tmp : end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31444 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31445 | p1 = utfnshift(p1, fromIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31446 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31447 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31448 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31449 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31450 | * TODO(dfrank): when `last` is set, start from the end and look |
Marko Mikulicic |
0:c0ecb8bf28eb | 31451 | * backward. We'll need to improve `utfnshift()` for that, so that it can |
Marko Mikulicic |
0:c0ecb8bf28eb | 31452 | * handle negative offsets. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31453 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31454 | for (i = 0; p1 <= (end - bytecnt2); i++, p1 = utfnshift(p1, 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31455 | if (memcmp(p1, p2, bytecnt2) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31456 | dres = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31457 | if (!last) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31458 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31459 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31460 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31462 | if (!last && dres >= 0) dres += fromIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31463 | *res = v7_mk_number(v7, dres); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31464 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31465 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31466 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31467 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31468 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31469 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31470 | V7_PRIVATE enum v7_err Str_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31471 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31472 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31473 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31474 | if (!v7_is_string(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31475 | (v7_is_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31476 | v7_get_proto(v7, this_obj) != v7->vals.string_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31477 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31478 | v7_throwf(v7, TYPE_ERROR, "String.valueOf called on non-string object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31479 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31481 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31482 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31483 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31484 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31485 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31486 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31487 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31488 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31489 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31490 | V7_PRIVATE enum v7_err Str_indexOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31491 | return s_index_of(v7, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31492 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31493 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31494 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31495 | V7_PRIVATE enum v7_err Str_lastIndexOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31496 | return s_index_of(v7, 1, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31497 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31498 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31499 | #if V7_ENABLE__String__localeCompare |
Marko Mikulicic |
0:c0ecb8bf28eb | 31500 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31501 | V7_PRIVATE enum v7_err Str_localeCompare(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31502 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31503 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31504 | val_t arg0 = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31505 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31506 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31507 | rcode = to_string(v7, v7_arg(v7, 0), &arg0, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31508 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31509 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31510 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31511 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31512 | rcode = to_string(v7, this_obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31513 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31514 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31516 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31517 | *res = v7_mk_number(v7, s_cmp(v7, s, arg0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31518 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31519 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31520 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31521 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31522 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 31523 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31524 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31525 | V7_PRIVATE enum v7_err Str_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31526 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31527 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31529 | if (this_obj == v7->vals.string_prototype) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31530 | *res = v7_mk_string(v7, "false", 5, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31531 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31532 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31533 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31534 | if (!v7_is_string(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31535 | !(v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31536 | is_prototype_of(v7, this_obj, v7->vals.string_prototype))) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31537 | rcode = v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31538 | "String.toString called on non-string object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31539 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31540 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31542 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31543 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31544 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31545 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31546 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31547 | rcode = to_string(v7, this_obj, res, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31548 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31549 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31550 | } |
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 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 31557 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31558 | enum v7_err call_regex_ctor(struct v7 *v7, val_t arg, val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31559 | /* TODO(mkm): make general helper out of this */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31560 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31561 | val_t saved_args = v7->vals.arguments, args = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31562 | v7_array_push(v7, args, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31563 | v7->vals.arguments = args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31564 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31565 | rcode = Regex_ctor(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31566 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31567 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31568 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31569 | v7->vals.arguments = saved_args; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31571 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31572 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31573 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31574 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31575 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31576 | V7_PRIVATE enum v7_err Str_match(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31577 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31578 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31579 | val_t so = V7_UNDEFINED, ro = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31580 | long previousLastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31581 | int lastMatch = 1, n = 0, flag_g; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31582 | struct v7_regexp *rxp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31584 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31586 | rcode = to_string(v7, this_obj, &so, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31587 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31588 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31589 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31590 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31591 | if (v7_argc(v7) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31592 | rcode = v7_mk_regexp(v7, "", 0, "", 0, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31593 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31594 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31596 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31597 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31598 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31599 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31600 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31601 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31602 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31603 | if (!v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31604 | rcode = call_regex_ctor(v7, ro, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31605 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31606 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31607 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31608 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31609 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31610 | rxp = v7_get_regexp_struct(v7, ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31611 | flag_g = slre_get_flags(rxp->compiled_regexp) & SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31612 | if (!flag_g) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31613 | rcode = rx_exec(v7, ro, so, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31614 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31615 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31616 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31617 | rxp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31618 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31619 | while (lastMatch) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31620 | val_t result; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31621 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31622 | rcode = rx_exec(v7, ro, so, 1, &result); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31623 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31624 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31625 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31626 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31627 | if (v7_is_null(result)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31628 | lastMatch = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31629 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31630 | long thisIndex = rxp->lastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31631 | if (thisIndex == previousLastIndex) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31632 | previousLastIndex = thisIndex + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31633 | rxp->lastIndex = previousLastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31634 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31635 | previousLastIndex = thisIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31636 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31637 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 31638 | v7_array_push_throwing(v7, *res, v7_array_get(v7, result, 0), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31639 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31640 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31641 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31642 | n++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31643 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31644 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31645 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31646 | if (n == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31647 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31648 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31649 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31651 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31652 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31653 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31655 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31656 | V7_PRIVATE enum v7_err Str_replace(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31657 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31658 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31659 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31660 | size_t s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31661 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 31662 | * Buffer of temporary strings returned by the replacement funciton. Will be |
Marko Mikulicic |
0:c0ecb8bf28eb | 31663 | * allocated below if only the replacement is a function. We need to store |
Marko Mikulicic |
0:c0ecb8bf28eb | 31664 | * each string in a separate `val_t`, because string data of length <= 5 is |
Marko Mikulicic |
0:c0ecb8bf28eb | 31665 | * stored right in `val_t`, so if there's more than one replacement, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31666 | * each subsequent replacement will overwrite the previous one. |
Marko Mikulicic |
0:c0ecb8bf28eb | 31667 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31668 | val_t *tmp_str_buf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31669 | val_t out_str_o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31670 | char *old_owned_mbuf_base = v7->owned_strings.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31671 | char *old_owned_mbuf_end = v7->owned_strings.buf + v7->owned_strings.len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31672 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31673 | rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31674 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31675 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31676 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31677 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31678 | s = v7_get_string(v7, &this_obj, &s_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31680 | if (s_len != 0 && v7_argc(v7) > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31681 | const char *const str_end = s + s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31682 | char *p = (char *) s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31683 | uint32_t out_sub_num = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31684 | val_t ro = V7_UNDEFINED, str_func = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31685 | struct slre_prog *prog; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31686 | struct slre_cap out_sub[V7_RE_MAX_REPL_SUB], *ptok = out_sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31687 | struct slre_loot loot; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31688 | int flag_g; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31690 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
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 | rcode = obj_value_of(v7, v7_arg(v7, 1), &str_func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31695 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31696 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31697 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31698 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31699 | if (!v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31700 | rcode = call_regex_ctor(v7, ro, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31701 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31702 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31703 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31704 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31705 | prog = v7_get_regexp_struct(v7, ro)->compiled_regexp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31706 | flag_g = slre_get_flags(prog) & SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31708 | if (!v7_is_callable(v7, str_func)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31709 | rcode = to_string(v7, str_func, &str_func, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31710 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31711 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31712 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31713 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31714 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31715 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31716 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31717 | if (slre_exec(prog, 0, p, str_end, &loot)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31718 | if (p != loot.caps->start) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31719 | ptok->start = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31720 | ptok->end = loot.caps->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31721 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31722 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31723 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31725 | if (v7_is_callable(v7, str_func)) { /* replace function */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31726 | const char *rez_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31727 | size_t rez_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31728 | val_t arr = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31729 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31730 | for (i = 0; i < loot.num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31731 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 31732 | v7, arr, v7_mk_string(v7, loot.caps[i].start, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31733 | loot.caps[i].end - loot.caps[i].start, 1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31734 | NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31735 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31736 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31737 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31738 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31739 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 31740 | v7, arr, v7_mk_number(v7, utfnlen(s, loot.caps[0].start - s)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31741 | NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31742 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31743 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31744 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31745 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31746 | rcode = v7_array_push_throwing(v7, arr, this_obj, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31747 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31748 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31749 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31750 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31751 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31752 | val_t val = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31754 | rcode = b_apply(v7, str_func, this_obj, arr, 0, &val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31755 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31756 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31757 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31758 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31759 | if (tmp_str_buf == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31760 | tmp_str_buf = (val_t *) calloc(sizeof(val_t), V7_RE_MAX_REPL_SUB); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31761 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31762 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31763 | rcode = to_string(v7, val, &tmp_str_buf[out_sub_num], NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31764 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31765 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31766 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31767 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31768 | rez_str = v7_get_string(v7, &tmp_str_buf[out_sub_num], &rez_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31769 | if (rez_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31770 | ptok->start = rez_str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31771 | ptok->end = rez_str + rez_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31772 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31773 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31774 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31775 | } else { /* replace string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31776 | struct slre_loot newsub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31777 | size_t f_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31778 | const char *f_str = v7_get_string(v7, &str_func, &f_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31779 | slre_replace(&loot, s, s_len, f_str, f_len, &newsub); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31780 | for (i = 0; i < newsub.num_captures; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31781 | ptok->start = newsub.caps[i].start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31782 | ptok->end = newsub.caps[i].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31783 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31784 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31785 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31786 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31787 | p = (char *) loot.caps[0].end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31788 | } while (flag_g && p < str_end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31789 | if (p <= str_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31790 | ptok->start = p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31791 | ptok->end = str_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31792 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31793 | out_sub_num++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31794 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31795 | out_str_o = v7_mk_string(v7, NULL, 0, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31796 | ptok = out_sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31797 | do { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31798 | size_t ln = ptok->end - ptok->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31799 | const char *ps = ptok->start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31800 | if (ptok->start >= old_owned_mbuf_base && |
Marko Mikulicic |
0:c0ecb8bf28eb | 31801 | ptok->start < old_owned_mbuf_end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31802 | ps += v7->owned_strings.buf - old_owned_mbuf_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31803 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31804 | out_str_o = s_concat(v7, out_str_o, v7_mk_string(v7, ps, ln, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31805 | p += ln; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31806 | ptok++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31807 | } while (--out_sub_num); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31809 | *res = out_str_o; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31810 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31811 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31812 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31813 | *res = this_obj; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31815 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31816 | if (tmp_str_buf != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31817 | free(tmp_str_buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31818 | tmp_str_buf = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31819 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31820 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31821 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31822 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31823 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31824 | V7_PRIVATE enum v7_err Str_search(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31825 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31826 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31827 | long utf_shift = -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31829 | if (v7_argc(v7) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31830 | size_t s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31831 | struct slre_loot sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31832 | val_t so = V7_UNDEFINED, ro = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31833 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31835 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31836 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31837 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31838 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31840 | if (!v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31841 | rcode = call_regex_ctor(v7, ro, &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31842 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31843 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31844 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31845 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31846 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31847 | rcode = to_string(v7, this_obj, &so, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31848 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31849 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31850 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31851 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31852 | s = v7_get_string(v7, &so, &s_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31854 | if (!slre_exec(v7_get_regexp_struct(v7, ro)->compiled_regexp, 0, s, |
Marko Mikulicic |
0:c0ecb8bf28eb | 31855 | s + s_len, &sub)) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31856 | utf_shift = utfnlen(s, sub.caps[0].start - s); /* calc shift for UTF-8 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31857 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31858 | utf_shift = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31859 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31860 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31861 | *res = v7_mk_number(v7, utf_shift); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31862 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31863 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31864 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31865 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31866 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31867 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31869 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31870 | V7_PRIVATE enum v7_err Str_slice(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31871 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31872 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31873 | long from = 0, to = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31874 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31875 | val_t so = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31876 | const char *begin, *end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31877 | int num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31878 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31879 | rcode = to_string(v7, this_obj, &so, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31880 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31881 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31882 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31884 | begin = v7_get_string(v7, &so, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31886 | to = len = utfnlen(begin, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31887 | if (num_args > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31888 | rcode = to_long(v7, v7_arg(v7, 0), 0, &from); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31889 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31890 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31892 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31893 | if (from < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31894 | from += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31895 | if (from < 0) from = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31896 | } else if ((size_t) from > len) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31897 | from = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31898 | if (num_args > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31899 | rcode = to_long(v7, v7_arg(v7, 1), 0, &to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31900 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31901 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31902 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31903 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31904 | if (to < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31905 | to += len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31906 | if (to < 0) to = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31907 | } else if ((size_t) to > len) |
Marko Mikulicic |
0:c0ecb8bf28eb | 31908 | to = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31909 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31912 | if (from > to) to = from; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31913 | end = utfnshift(begin, to); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31914 | begin = utfnshift(begin, from); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31915 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31916 | *res = v7_mk_string(v7, begin, end - begin, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31917 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31918 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31919 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31920 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31921 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31922 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31923 | static enum v7_err s_transform(struct v7 *v7, val_t obj, Rune (*func)(Rune), |
Marko Mikulicic |
0:c0ecb8bf28eb | 31924 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31925 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31926 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31927 | size_t i, n, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31928 | const char *p2, *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31930 | rcode = to_string(v7, obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31931 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31932 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31933 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31934 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31935 | p = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31937 | /* Pass NULL to make sure we're not creating dictionary value */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 31938 | *res = v7_mk_string(v7, NULL, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31940 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31941 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31942 | p2 = v7_get_string(v7, res, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31943 | for (i = 0; i < len; i += n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31944 | n = chartorune(&r, p + i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31945 | r = func(r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31946 | runetochar((char *) p2 + i, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31947 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31948 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31950 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31951 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31952 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31954 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31955 | V7_PRIVATE enum v7_err Str_toLowerCase(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31956 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31957 | return s_transform(v7, this_obj, tolowerrune, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31958 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31959 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31960 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31961 | V7_PRIVATE enum v7_err Str_toUpperCase(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31962 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31963 | return s_transform(v7, this_obj, toupperrune, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31964 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31965 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31966 | static int s_isspace(Rune c) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31967 | return isspacerune(c) || isnewline(c); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31968 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31969 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31970 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 31971 | V7_PRIVATE enum v7_err Str_trim(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31972 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31973 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31974 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31975 | size_t i, n, len, start = 0, end, state = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31976 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31977 | Rune r; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31978 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31979 | rcode = to_string(v7, this_obj, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31980 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31981 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31982 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31983 | p = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31984 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31985 | end = len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31986 | for (i = 0; i < len; i += n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31987 | n = chartorune(&r, p + i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31988 | if (!s_isspace(r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 31989 | if (state++ == 0) start = i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31990 | end = i + n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31991 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31992 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31993 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31994 | *res = v7_mk_string(v7, p + start, end - start, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 31995 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 31996 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 31997 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 31998 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 31999 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32000 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32001 | V7_PRIVATE enum v7_err Str_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32002 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32003 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32004 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32005 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32007 | rcode = obj_value_of(v7, this_obj, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32008 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32009 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32010 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32011 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32012 | if (v7_is_string(s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32013 | const char *p = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32014 | len = utfnlen(p, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32015 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32016 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32017 | *res = v7_mk_number(v7, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32018 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32019 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32020 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32021 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32022 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32023 | V7_PRIVATE enum v7_err Str_at(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32024 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32025 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32026 | long arg0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32027 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32028 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32029 | rcode = to_long(v7, v7_arg(v7, 0), -1, &arg0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32030 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32031 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32032 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32033 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32034 | rcode = obj_value_of(v7, this_obj, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32035 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32036 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32038 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32039 | if (v7_is_string(s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32040 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32041 | const unsigned char *p = (unsigned char *) v7_get_string(v7, &s, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32042 | if (arg0 >= 0 && (size_t) arg0 < n) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32043 | *res = v7_mk_number(v7, p[arg0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32044 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32045 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32046 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32047 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32048 | *res = v7_mk_number(v7, NAN); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32049 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32050 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32051 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32052 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32054 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32055 | V7_PRIVATE enum v7_err Str_blen(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32056 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32057 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32058 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32059 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32060 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32061 | rcode = obj_value_of(v7, this_obj, &s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32062 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32063 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32064 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32065 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32066 | if (v7_is_string(s)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32067 | v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32068 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32070 | *res = v7_mk_number(v7, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32072 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32073 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32074 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32075 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32076 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32077 | static enum v7_err s_substr(struct v7 *v7, val_t s, long start, long len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32078 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32079 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32080 | size_t n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32081 | const char *p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32083 | rcode = to_string(v7, s, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32084 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32085 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32086 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32087 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32088 | p = v7_get_string(v7, &s, &n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32089 | n = utfnlen(p, n); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32091 | if (start < (long) n && len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32092 | if (start < 0) start = (long) n + start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32093 | if (start < 0) start = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32094 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32095 | if (start > (long) n) start = n; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32096 | if (len < 0) len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32097 | if (len > (long) n - start) len = n - start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32098 | p = utfnshift(p, start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32099 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32100 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32101 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32102 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32103 | *res = v7_mk_string(v7, p, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32104 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32105 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32106 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32107 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32109 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32110 | V7_PRIVATE enum v7_err Str_substr(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32111 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32112 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32113 | long start, len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32114 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32115 | rcode = to_long(v7, v7_arg(v7, 0), 0, &start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32116 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32117 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32118 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32119 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32120 | rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32121 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32122 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32123 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32125 | rcode = s_substr(v7, this_obj, start, len, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32126 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32127 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32128 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32129 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32130 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32131 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32132 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32134 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32135 | V7_PRIVATE enum v7_err Str_substring(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32136 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32137 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32138 | long start, end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32140 | rcode = to_long(v7, v7_arg(v7, 0), 0, &start); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32141 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32142 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32143 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32144 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32145 | rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &end); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32146 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32147 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32148 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32149 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32150 | if (start < 0) start = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32151 | if (end < 0) end = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32152 | if (start > end) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32153 | long tmp = start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32154 | start = end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32155 | end = tmp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32156 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32158 | rcode = s_substr(v7, this_obj, start, end - start, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32159 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32160 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32161 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32162 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32163 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32164 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32165 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32166 | V7_PRIVATE enum v7_err Str_split(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32167 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32168 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32169 | const char *s, *s_end; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32170 | size_t s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32171 | long num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32172 | rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32173 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32174 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32175 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32176 | s = v7_get_string(v7, &this_obj, &s_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32177 | s_end = s + s_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32178 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32179 | *res = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32180 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32181 | if (num_args == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32182 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32183 | * No arguments were given: resulting array will contain just a single |
Marko Mikulicic |
0:c0ecb8bf28eb | 32184 | * element: the source string |
Marko Mikulicic |
0:c0ecb8bf28eb | 32185 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32186 | rcode = v7_array_push_throwing(v7, *res, this_obj, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32187 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32188 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32189 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32190 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32191 | val_t ro = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32192 | long elem, limit; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32193 | size_t lookup_idx = 0, substr_idx = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32194 | struct _str_split_ctx ctx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32195 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32196 | rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32197 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32198 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32199 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32200 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32201 | rcode = obj_value_of(v7, v7_arg(v7, 0), &ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32202 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32203 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32204 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32205 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32206 | /* Initialize substring context depending on the argument type */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32207 | if (v7_is_regexp(v7, ro)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32208 | /* use RegExp implementation */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32209 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32210 | ctx.p_init = subs_regexp_init; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32211 | ctx.p_exec = subs_regexp_exec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32212 | ctx.p_add_caps = subs_regexp_split_add_caps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32213 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 32214 | assert(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32215 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32216 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32217 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32218 | * use String implementation: first of all, convert to String (if it's |
Marko Mikulicic |
0:c0ecb8bf28eb | 32219 | * not already a String) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32220 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32221 | rcode = to_string(v7, ro, &ro, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32222 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32223 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32224 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32226 | ctx.p_init = subs_string_init; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32227 | ctx.p_exec = subs_string_exec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32228 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32229 | ctx.p_add_caps = subs_string_split_add_caps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32230 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32231 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32232 | /* initialize context */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32233 | ctx.p_init(&ctx, v7, ro); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32234 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32235 | if (s_len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32236 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32237 | * if `this` is (or converts to) an empty string, resulting array should |
Marko Mikulicic |
0:c0ecb8bf28eb | 32238 | * contain empty string if only separator does not match an empty string. |
Marko Mikulicic |
0:c0ecb8bf28eb | 32239 | * Otherwise, the array is left empty |
Marko Mikulicic |
0:c0ecb8bf28eb | 32240 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32241 | int matches_empty = !ctx.p_exec(&ctx, s, s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32242 | if (!matches_empty) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32243 | rcode = v7_array_push_throwing(v7, *res, this_obj, 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 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32248 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32249 | size_t last_match_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32251 | for (elem = 0; elem < limit && lookup_idx < s_len;) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32252 | size_t substr_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32253 | /* find next match, and break if there's no match */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32254 | if (ctx.p_exec(&ctx, s + lookup_idx, s_end)) break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32255 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32256 | last_match_len = ctx.match_end - ctx.match_start; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32257 | substr_len = ctx.match_start - s - substr_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32258 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32259 | /* add next substring to the resulting array, if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32260 | if (substr_len > 0 || last_match_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32261 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 32262 | v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32263 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32264 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32265 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32266 | elem++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32267 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32268 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32269 | /* Add captures (for RegExp only) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32270 | elem = ctx.p_add_caps(&ctx, *res, elem, limit); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32271 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32272 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32273 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32274 | /* advance lookup_idx appropriately */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32275 | if (last_match_len == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32276 | /* empty match: advance to the next char */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32277 | const char *next = utfnshift((s + lookup_idx), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32278 | lookup_idx += (next - (s + lookup_idx)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32279 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32280 | /* non-empty match: advance to the end of match */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32281 | lookup_idx = ctx.match_end - s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32282 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32283 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32284 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32285 | * always remember the end of the match, so that next time we will take |
Marko Mikulicic |
0:c0ecb8bf28eb | 32286 | * substring from that position |
Marko Mikulicic |
0:c0ecb8bf28eb | 32287 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32288 | substr_idx = ctx.match_end - s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32289 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32290 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32291 | /* add the last substring to the resulting array, if needed */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32292 | if (elem < limit) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32293 | size_t substr_len = s_len - substr_idx; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32294 | if (substr_len > 0 || last_match_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32295 | rcode = v7_array_push_throwing( |
Marko Mikulicic |
0:c0ecb8bf28eb | 32296 | v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32297 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32298 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32299 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32300 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32301 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32302 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32303 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32304 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32305 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32306 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32307 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32309 | V7_PRIVATE void init_string(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32310 | val_t str = mk_cfunction_obj_with_proto(v7, String_ctor, 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32311 | v7->vals.string_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32312 | v7_def(v7, v7->vals.global_object, "String", 6, V7_DESC_ENUMERABLE(0), str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32313 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32314 | set_cfunc_prop(v7, str, "fromCharCode", Str_fromCharCode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32315 | set_cfunc_prop(v7, v7->vals.string_prototype, "charCodeAt", Str_charCodeAt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32316 | set_cfunc_prop(v7, v7->vals.string_prototype, "charAt", Str_charAt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32317 | set_cfunc_prop(v7, v7->vals.string_prototype, "concat", Str_concat); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32318 | set_cfunc_prop(v7, v7->vals.string_prototype, "indexOf", Str_indexOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32319 | set_cfunc_prop(v7, v7->vals.string_prototype, "substr", Str_substr); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32320 | set_cfunc_prop(v7, v7->vals.string_prototype, "substring", Str_substring); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32321 | set_cfunc_prop(v7, v7->vals.string_prototype, "valueOf", Str_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32322 | set_cfunc_prop(v7, v7->vals.string_prototype, "lastIndexOf", Str_lastIndexOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32323 | #if V7_ENABLE__String__localeCompare |
Marko Mikulicic |
0:c0ecb8bf28eb | 32324 | set_cfunc_prop(v7, v7->vals.string_prototype, "localeCompare", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32325 | Str_localeCompare); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32326 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32327 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 32328 | set_cfunc_prop(v7, v7->vals.string_prototype, "match", Str_match); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32329 | set_cfunc_prop(v7, v7->vals.string_prototype, "replace", Str_replace); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32330 | set_cfunc_prop(v7, v7->vals.string_prototype, "search", Str_search); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32331 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32332 | set_cfunc_prop(v7, v7->vals.string_prototype, "split", Str_split); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32333 | set_cfunc_prop(v7, v7->vals.string_prototype, "slice", Str_slice); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32334 | set_cfunc_prop(v7, v7->vals.string_prototype, "trim", Str_trim); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32335 | set_cfunc_prop(v7, v7->vals.string_prototype, "toLowerCase", Str_toLowerCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32336 | #if V7_ENABLE__String__localeLowerCase |
Marko Mikulicic |
0:c0ecb8bf28eb | 32337 | set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleLowerCase", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32338 | Str_toLowerCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32339 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32340 | set_cfunc_prop(v7, v7->vals.string_prototype, "toUpperCase", Str_toUpperCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32341 | #if V7_ENABLE__String__localeUpperCase |
Marko Mikulicic |
0:c0ecb8bf28eb | 32342 | set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleUpperCase", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32343 | Str_toUpperCase); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32344 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32345 | set_cfunc_prop(v7, v7->vals.string_prototype, "toString", Str_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32346 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32347 | v7_def(v7, v7->vals.string_prototype, "length", 6, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32348 | v7_mk_cfunction(Str_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32349 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32350 | /* Non-standard Cesanta extension */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32351 | set_cfunc_prop(v7, v7->vals.string_prototype, "at", Str_at); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32352 | v7_def(v7, v7->vals.string_prototype, "blen", 4, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32353 | v7_mk_cfunction(Str_blen)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32354 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32355 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 32356 | #line 1 "v7/src/std_date.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 32357 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32358 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32359 | * Copyright (c) 2015 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 32360 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 32361 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32362 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32363 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32364 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32365 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32366 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32367 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32368 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32369 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32370 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32371 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32372 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32373 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32374 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32375 | #if V7_ENABLE__Date |
Marko Mikulicic |
0:c0ecb8bf28eb | 32376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32377 | #include <locale.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 32378 | #include <time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 32379 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32380 | #ifndef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32381 | extern long timezone; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32382 | #include <sys/time.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 32383 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32385 | #if defined(_MSC_VER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32386 | #define timezone _timezone |
Marko Mikulicic |
0:c0ecb8bf28eb | 32387 | #define tzname _tzname |
Marko Mikulicic |
0:c0ecb8bf28eb | 32388 | #if _MSC_VER >= 1800 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32389 | #define tzset _tzset |
Marko Mikulicic |
0:c0ecb8bf28eb | 32390 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32391 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32393 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32394 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32395 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32397 | typedef double etime_t; /* double is suitable type for ECMA time */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32398 | /* inernally we have to use 64-bit integer for some operations */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32399 | typedef int64_t etimeint_t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32400 | #define INVALID_TIME NAN |
Marko Mikulicic |
0:c0ecb8bf28eb | 32401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32402 | #define msPerDay 86400000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32403 | #define HoursPerDay 24 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32404 | #define MinutesPerHour 60 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32405 | #define SecondsPerMinute 60 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32406 | #define SecondsPerHour 3600 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32407 | #define msPerSecond 1000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32408 | #define msPerMinute 60000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32409 | #define msPerHour 3600000 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32410 | #define MonthsInYear 12 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32412 | /* ECMA alternative to struct tm */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32413 | struct timeparts { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32414 | int year; /* can be negative, up to +-282000 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32415 | int month; /* 0-11 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32416 | int day; /* 1-31 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32417 | int hour; /* 0-23 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32418 | int min; /* 0-59 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32419 | int sec; /* 0-59 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32420 | int msec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32421 | int dayofweek; /* 0-6 */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32422 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32423 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32424 | static etimeint_t g_gmtoffms; /* timezone offset, ms, no DST */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32425 | static const char *g_tzname; /* current timezone name */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32426 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32427 | /* Leap year formula copied from ECMA 5.1 standart as is */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32428 | static int ecma_DaysInYear(int y) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32429 | if (y % 4 != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32430 | return 365; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32431 | } else if (y % 4 == 0 && y % 100 != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32432 | return 366; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32433 | } else if (y % 100 == 0 && y % 400 != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32434 | return 365; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32435 | } else if (y % 400 == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32436 | return 366; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32437 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32438 | return 365; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32439 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32440 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32441 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32442 | static etimeint_t ecma_DayFromYear(etimeint_t y) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32443 | return 365 * (y - 1970) + floor((y - 1969) / 4) - floor((y - 1901) / 100) + |
Marko Mikulicic |
0:c0ecb8bf28eb | 32444 | floor((y - 1601) / 400); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32445 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32446 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32447 | static etimeint_t ecma_TimeFromYear(etimeint_t y) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32448 | return msPerDay * ecma_DayFromYear(y); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32449 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32451 | static int ecma_IsLeapYear(int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32452 | return ecma_DaysInYear(year) == 366; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32453 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32454 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32455 | static int *ecma_getfirstdays(int isleap) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32456 | static int sdays[2][MonthsInYear + 1] = { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32457 | {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32458 | {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32460 | return sdays[isleap]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32461 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32462 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32463 | static int ecma_DaylightSavingTA(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32464 | time_t time = t / 1000; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32465 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32466 | * Win32 doesn't have locatime_r |
Marko Mikulicic |
0:c0ecb8bf28eb | 32467 | * nixes don't have localtime_s |
Marko Mikulicic |
0:c0ecb8bf28eb | 32468 | * as result using localtime |
Marko Mikulicic |
0:c0ecb8bf28eb | 32469 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32470 | struct tm *tm = localtime(&time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32471 | if (tm == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32472 | /* doesn't work on windows for times before epoch */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32473 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32474 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32475 | if (tm->tm_isdst > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32476 | return msPerHour; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32477 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32478 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32479 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32480 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32481 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32482 | static int ecma_LocalTZA(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32483 | return (int) -g_gmtoffms; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32484 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32485 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32486 | static etimeint_t ecma_UTC(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32487 | return t - ecma_LocalTZA() - ecma_DaylightSavingTA(t - ecma_LocalTZA()); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32488 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32489 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32490 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32491 | V7_ENABLE__Date__toJSON || V7_ENABLE__Date__getters || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32492 | V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 32493 | static int ecma_YearFromTime_s(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32494 | int first = floor((t / msPerDay) / 366) + 1970, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32495 | last = floor((t / msPerDay) / 365) + 1970, middle = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32496 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32497 | if (last < first) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32498 | int temp = first; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32499 | first = last; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32500 | last = temp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32501 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32502 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32503 | while (last > first) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32504 | middle = (last + first) / 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32505 | if (ecma_TimeFromYear(middle) > t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32506 | last = middle - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32507 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32508 | if (ecma_TimeFromYear(middle) <= t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32509 | if (ecma_TimeFromYear(middle + 1) > t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32510 | first = middle; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32511 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32512 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32513 | first = middle + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32514 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32515 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32516 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32517 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32518 | return first; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32519 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32520 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32521 | static etimeint_t ecma_Day(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32522 | return floor(t / msPerDay); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32523 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32525 | static int ecma_DayWithinYear(etime_t t, int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32526 | return (int) (ecma_Day(t) - ecma_DayFromYear(year)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32527 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32528 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32529 | static int ecma_MonthFromTime(etime_t t, int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32530 | int *days, i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32531 | etimeint_t dwy = ecma_DayWithinYear(t, year); |
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 | for (i = 0; i < MonthsInYear; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32536 | if (dwy >= days[i] && dwy < days[i + 1]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32537 | return i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32538 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32539 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32540 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32541 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32542 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32543 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32544 | static int ecma_DateFromTime(etime_t t, int year) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32545 | int *days, mft = ecma_MonthFromTime(t, year), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32546 | dwy = ecma_DayWithinYear(t, year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32547 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32548 | if (mft > 11) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32549 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32550 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32551 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32552 | days = ecma_getfirstdays(ecma_IsLeapYear(year)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32553 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32554 | return dwy - days[mft] + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32555 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32556 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32557 | #define DEF_EXTRACT_TIMEPART(funcname, c1, c2) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32558 | static int ecma_##funcname(etime_t t) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32559 | int ret = (etimeint_t) floor(t / c1) % c2; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32560 | if (ret < 0) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32561 | ret += c2; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32562 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32563 | return ret; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32564 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32565 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32566 | DEF_EXTRACT_TIMEPART(HourFromTime, msPerHour, HoursPerDay) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32567 | DEF_EXTRACT_TIMEPART(MinFromTime, msPerMinute, MinutesPerHour) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32568 | DEF_EXTRACT_TIMEPART(SecFromTime, msPerSecond, SecondsPerMinute) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32569 | DEF_EXTRACT_TIMEPART(msFromTime, 1, msPerSecond) |
Marko Mikulicic |
0:c0ecb8bf28eb | 32570 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32571 | static int ecma_WeekDay(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32572 | int ret = (ecma_Day(t) + 4) % 7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32573 | if (ret < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32574 | ret += 7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32575 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32576 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32577 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32578 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32580 | static void d_gmtime(const etime_t *t, struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32581 | tp->year = ecma_YearFromTime_s(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32582 | tp->month = ecma_MonthFromTime(*t, tp->year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32583 | tp->day = ecma_DateFromTime(*t, tp->year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32584 | tp->hour = ecma_HourFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32585 | tp->min = ecma_MinFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32586 | tp->sec = ecma_SecFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32587 | tp->msec = ecma_msFromTime(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32588 | tp->dayofweek = ecma_WeekDay(*t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32589 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32590 | #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32591 | V7_ENABLE__Date__getters || V7_ENABLE__Date__setters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32592 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32593 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32594 | V7_ENABLE__Date__getters || V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 32595 | static etimeint_t ecma_LocalTime(etime_t t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32596 | return t + ecma_LocalTZA() + ecma_DaylightSavingTA(t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32597 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32598 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32599 | static void d_localtime(const etime_t *time, struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32600 | etime_t local_time = ecma_LocalTime(*time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32601 | d_gmtime(&local_time, tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32602 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32603 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32604 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32605 | static etimeint_t ecma_MakeTime(etimeint_t hour, etimeint_t min, etimeint_t sec, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32606 | etimeint_t ms) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32607 | return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * |
Marko Mikulicic |
0:c0ecb8bf28eb | 32608 | msPerSecond + |
Marko Mikulicic |
0:c0ecb8bf28eb | 32609 | ms; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32610 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32611 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32612 | static etimeint_t ecma_MakeDay(int year, int month, int date) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32613 | int *days; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32614 | etimeint_t yday, mday; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32615 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32616 | year += floor(month / 12); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32617 | month = month % 12; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32618 | yday = floor(ecma_TimeFromYear(year) / msPerDay); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32619 | days = ecma_getfirstdays(ecma_IsLeapYear(year)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32620 | mday = days[month]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32621 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32622 | return yday + mday + date - 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32623 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32624 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32625 | static etimeint_t ecma_MakeDate(etimeint_t day, etimeint_t time) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32626 | return (day * msPerDay + time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32627 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32628 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32629 | static void d_gettime(etime_t *t) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32630 | #ifndef _WIN32 |
Marko Mikulicic |
0:c0ecb8bf28eb | 32631 | struct timeval tv; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32632 | gettimeofday(&tv, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32633 | *t = (etime_t) tv.tv_sec * 1000 + (etime_t) tv.tv_usec / 1000; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32634 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 32635 | /* TODO(mkm): use native windows API in order to get ms granularity */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32636 | *t = time(NULL) * 1000.0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32637 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32638 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32639 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32640 | static etime_t d_mktime_impl(const struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32641 | return ecma_MakeDate(ecma_MakeDay(tp->year, tp->month, tp->day), |
Marko Mikulicic |
0:c0ecb8bf28eb | 32642 | ecma_MakeTime(tp->hour, tp->min, tp->sec, tp->msec)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32643 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32644 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32645 | #if V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 32646 | static etime_t d_lmktime(const struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32647 | return ecma_UTC(d_mktime_impl(tp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32648 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32649 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32650 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32651 | static etime_t d_gmktime(const struct timeparts *tp) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32652 | return d_mktime_impl(tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32653 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32654 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32655 | typedef etime_t (*fmaketime_t)(const struct timeparts *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32656 | typedef void (*fbreaktime_t)(const etime_t *, struct timeparts *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32657 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32658 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32659 | V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 32660 | static val_t d_trytogetobjforstring(struct v7 *v7, val_t obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32661 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32662 | val_t ret = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32663 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32664 | rcode = obj_value_of(v7, obj, &ret); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32665 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32666 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32667 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32668 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32669 | if (ret == V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32670 | rcode = v7_throwf(v7, TYPE_ERROR, "Date is invalid (for string)"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32671 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32672 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32674 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32675 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32676 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32678 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32679 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32680 | #if V7_ENABLE__Date__parse || V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 32681 | static int d_iscalledasfunction(struct v7 *v7, val_t this_obj) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32682 | /* TODO(alashkin): verify this statement */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32683 | return is_prototype_of(v7, this_obj, v7->vals.date_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32684 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32685 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32686 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32687 | static const char *mon_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
Marko Mikulicic |
0:c0ecb8bf28eb | 32688 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32689 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32690 | int d_getnumbyname(const char **arr, int arr_size, const char *str) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32691 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32692 | for (i = 0; i < arr_size; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32693 | if (strncmp(arr[i], str, 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32694 | return i + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32695 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32696 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32697 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32698 | return -1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32699 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32700 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32701 | int date_parse(const char *str, int *a1, int *a2, int *a3, char sep, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32702 | char *rest) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32703 | char frmDate[] = " %d/%d/%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32704 | frmDate[3] = frmDate[6] = sep; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32705 | return sscanf(str, frmDate, a1, a2, a3, rest); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32706 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32707 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32708 | #define NO_TZ 0x7FFFFFFF |
Marko Mikulicic |
0:c0ecb8bf28eb | 32709 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32710 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32711 | * not very smart but simple, and working according |
Marko Mikulicic |
0:c0ecb8bf28eb | 32712 | * to ECMA5.1 StringToDate function |
Marko Mikulicic |
0:c0ecb8bf28eb | 32713 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32714 | static int d_parsedatestr(const char *jstr, size_t len, struct timeparts *tp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32715 | int *tz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32716 | char gmt[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32717 | char buf1[100] = {0}, buf2[100] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32718 | int res = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32719 | char str[101]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32720 | memcpy(str, jstr, len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32721 | str[len] = '\0'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32722 | memset(tp, 0, sizeof(*tp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32723 | *tz = NO_TZ; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32725 | /* trying toISOSrting() format */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32726 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32727 | const char *frmISOString = " %d-%02d-%02dT%02d:%02d:%02d.%03dZ"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32728 | res = sscanf(str, frmISOString, &tp->year, &tp->month, &tp->day, &tp->hour, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32729 | &tp->min, &tp->sec, &tp->msec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32730 | if (res == 7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32731 | *tz = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32732 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32733 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32734 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32735 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32736 | /* trying toString()/toUTCString()/toDateFormat() formats */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32737 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32738 | char month[4]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32739 | int dowlen; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32740 | const char *frmString = " %*s%n %03s %02d %d %02d:%02d:%02d %03s%d"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32741 | res = sscanf(str, frmString, &dowlen, month, &tp->day, &tp->year, &tp->hour, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32742 | &tp->min, &tp->sec, gmt, tz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32743 | if ((res == 3 || (res >= 6 && res <= 8)) && dowlen == 3) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32744 | if ((tp->month = d_getnumbyname(mon_name, ARRAY_SIZE(mon_name), month)) != |
Marko Mikulicic |
0:c0ecb8bf28eb | 32745 | -1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32746 | if (res == 7 && strncmp(gmt, "GMT", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32747 | *tz = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32748 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32749 | return 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32750 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32751 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32752 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32753 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32754 | /* trying the rest */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32755 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32756 | /* trying date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32757 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32758 | if (!(date_parse(str, &tp->month, &tp->day, &tp->year, '/', buf1) >= 3 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 32759 | date_parse(str, &tp->day, &tp->month, &tp->year, '.', buf1) >= 3 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 32760 | date_parse(str, &tp->year, &tp->month, &tp->day, '-', buf1) >= 3)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32761 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32762 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32763 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32764 | /* there is date, trying time; from here return 0 only on errors */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32765 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32766 | /* trying HH:mm */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32767 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32768 | const char *frmMMhh = " %d:%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32769 | res = sscanf(buf1, frmMMhh, &tp->hour, &tp->min, buf2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32770 | /* can't get time, but have some symbols, assuming error */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32771 | if (res < 2) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32772 | return (strlen(buf2) == 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32773 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32774 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32775 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32776 | /* trying seconds */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32777 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32778 | const char *frmss = ":%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32779 | memset(buf1, 0, sizeof(buf1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32780 | res = sscanf(buf2, frmss, &tp->sec, buf1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32781 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32782 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32783 | /* even if we don't get seconds we gonna try to get tz */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32784 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32785 | char *rest = res ? buf1 : buf2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32786 | char *buf = res ? buf2 : buf1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32787 | const char *frmtz = " %03s%d%[^\0]"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32788 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32789 | res = sscanf(rest, frmtz, gmt, tz, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32790 | if (res == 1 && strncmp(gmt, "GMT", 3) == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32791 | *tz = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32792 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32793 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32794 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32795 | /* return OK if we are at the end of string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32796 | return res <= 2; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32797 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32798 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32799 | static int d_timeFromString(etime_t *time, const char *str, size_t str_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32800 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32801 | int tz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32802 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32803 | *time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32804 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32805 | if (str_len > 100) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32806 | /* too long for valid date string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32807 | return 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32808 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32809 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32810 | if (d_parsedatestr(str, str_len, &tp, &tz)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32811 | /* check results */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32812 | int valid = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32813 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32814 | tp.month--; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32815 | valid = tp.day >= 1 && tp.day <= 31; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32816 | valid &= tp.month >= 0 && tp.month <= 11; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32817 | valid &= tp.hour >= 0 && tp.hour <= 23; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32818 | valid &= tp.min >= 0 && tp.min <= 59; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32819 | valid &= tp.sec >= 0 && tp.sec <= 59; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32820 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32821 | if (tz != NO_TZ && tz > 12) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32822 | tz /= 100; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32823 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32824 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32825 | valid &= (abs(tz) <= 12 || tz == NO_TZ); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32826 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32827 | if (valid) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32828 | *time = d_gmktime(&tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32829 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32830 | if (tz != NO_TZ) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32831 | /* timezone specified, use it */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32832 | *time -= (tz * msPerHour); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32833 | } else if (tz != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32834 | /* assuming local timezone and moving back to UTC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32835 | *time = ecma_UTC(*time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32836 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32837 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32838 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32839 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32840 | return !isnan(*time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32841 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32843 | /* notice: holding month in calendar format (1-12, not 0-11) */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32844 | struct dtimepartsarr { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32845 | etime_t args[7]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32846 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32847 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32848 | enum detimepartsarr { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32849 | tpyear = 0, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32850 | tpmonth, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32851 | tpdate, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32852 | tphours, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32853 | tpminutes, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32854 | tpseconds, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32855 | tpmsec, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32856 | tpmax |
Marko Mikulicic |
0:c0ecb8bf28eb | 32857 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32858 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32859 | static etime_t d_changepartoftime(const etime_t *current, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32860 | struct dtimepartsarr *a, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32861 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32862 | fmaketime_t maketimefunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32863 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32864 | * 0 = year, 1 = month , 2 = date , 3 = hours, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32865 | * 4 = minutes, 5 = seconds, 6 = ms |
Marko Mikulicic |
0:c0ecb8bf28eb | 32866 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32867 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32868 | unsigned long i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32869 | int *tp_arr[7]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32870 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32871 | * C89 doesn't allow initialization |
Marko Mikulicic |
0:c0ecb8bf28eb | 32872 | * like x = {&tp.year, &tp.month, .... } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32873 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32874 | tp_arr[0] = &tp.year; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32875 | tp_arr[1] = &tp.month; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32876 | tp_arr[2] = &tp.day; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32877 | tp_arr[3] = &tp.hour; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32878 | tp_arr[4] = &tp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32879 | tp_arr[5] = &tp.sec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32880 | tp_arr[6] = &tp.msec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32881 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32882 | memset(&tp, 0, sizeof(tp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32883 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32884 | if (breaktimefunc != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32885 | breaktimefunc(current, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32886 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32887 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32888 | for (i = 0; i < ARRAY_SIZE(tp_arr); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32889 | if (!isnan(a->args[i]) && !isinf(a->args[i])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32890 | *tp_arr[i] = (int) a->args[i]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32891 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32892 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32893 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32894 | return maketimefunc(&tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32895 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32896 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32897 | #if V7_ENABLE__Date__setters || V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 32898 | static etime_t d_time_number_from_arr(struct v7 *v7, int start_pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32899 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 32900 | fmaketime_t maketimefunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32901 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32902 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32903 | etime_t ret_time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32904 | long cargs; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32905 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32906 | val_t objtime = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32907 | rcode = obj_value_of(v7, this_obj, &objtime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32908 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32909 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32910 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32911 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32912 | if ((cargs = v7_argc(v7)) >= 1 && objtime != V7_TAG_NAN) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32913 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32914 | etime_t new_part = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32915 | struct dtimepartsarr a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32916 | for (i = 0; i < 7; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32917 | a.args[i] = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32918 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32919 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32920 | for (i = 0; i < cargs && (i + start_pos < tpmax); i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32921 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32922 | val_t arg = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32923 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32924 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32925 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32926 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32927 | new_part = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32928 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32930 | if (isnan(new_part)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32931 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32932 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32934 | a.args[i + start_pos] = new_part; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32935 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32936 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32937 | if (!isnan(new_part)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32938 | etime_t current_time = v7_get_double(v7, objtime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32939 | ret_time = |
Marko Mikulicic |
0:c0ecb8bf28eb | 32940 | d_changepartoftime(¤t_time, &a, breaktimefunc, maketimefunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32941 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32942 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32943 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32944 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 32945 | (void) rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32946 | return ret_time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32947 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32948 | #endif /* V7_ENABLE__Date__setters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32949 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32950 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 32951 | static int d_tptostr(const struct timeparts *tp, char *buf, int addtz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32952 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 32953 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32954 | /* constructor */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32955 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 32956 | V7_PRIVATE enum v7_err Date_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32957 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32958 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32959 | etime_t ret_time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32960 | if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32961 | long cargs = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32962 | if (cargs <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32963 | /* no parameters - return current date & time */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32964 | d_gettime(&ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32965 | } else if (cargs == 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32966 | /* one parameter */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32967 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32968 | if (v7_is_string(arg)) { /* it could be string */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32969 | size_t str_size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32970 | const char *str = v7_get_string(v7, &arg, &str_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32971 | d_timeFromString(&ret_time, str, str_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32972 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32973 | if (isnan(ret_time)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32974 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 32975 | * if cannot be parsed or |
Marko Mikulicic |
0:c0ecb8bf28eb | 32976 | * not string at all - trying to convert to number |
Marko Mikulicic |
0:c0ecb8bf28eb | 32977 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32978 | ret_time = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32979 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32980 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32981 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32982 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32983 | ret_time = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32984 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32985 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32986 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32987 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 32988 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32989 | /* 2+ paramaters - should be parts of a date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 32990 | struct dtimepartsarr a; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32991 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 32992 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32993 | memset(&a, 0, sizeof(a)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32994 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 32995 | for (i = 0; i < cargs; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32996 | val_t arg = v7_arg(v7, i); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32997 | rcode = to_number_v(v7, arg, &arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 32998 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 32999 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33000 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33001 | a.args[i] = v7_get_double(v7, arg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33002 | if (isnan(a.args[i])) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33003 | break; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33004 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33005 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33007 | if (i >= cargs) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33008 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33009 | * If date is supplied then let |
Marko Mikulicic |
0:c0ecb8bf28eb | 33010 | * dt be ToNumber(date); else let dt be 1. |
Marko Mikulicic |
0:c0ecb8bf28eb | 33011 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33012 | if (a.args[tpdate] == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33013 | a.args[tpdate] = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33014 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33015 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33016 | if (a.args[tpyear] >= 0 && a.args[tpyear] <= 99) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33017 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33018 | * If y is not NaN and 0 <= ToInteger(y) <= 99, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33019 | * then let yr be 1900+ToInteger(y); otherwise, let yr be y. |
Marko Mikulicic |
0:c0ecb8bf28eb | 33020 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33021 | a.args[tpyear] += 1900; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33022 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33024 | ret_time = ecma_UTC(d_changepartoftime(0, &a, 0, d_gmktime)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33025 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33027 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33028 | obj_prototype_set(v7, get_object_struct(this_obj), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33029 | get_object_struct(v7->vals.date_prototype)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33030 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33031 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_number(v7, ret_time)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33032 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33033 | * implicitly returning `this`: `call_cfunction()` in bcode.c will do |
Marko Mikulicic |
0:c0ecb8bf28eb | 33034 | * that for us |
Marko Mikulicic |
0:c0ecb8bf28eb | 33035 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33036 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33037 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33038 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33039 | * according to 15.9.2.1 we should ignore all |
Marko Mikulicic |
0:c0ecb8bf28eb | 33040 | * parameters in case of function-call |
Marko Mikulicic |
0:c0ecb8bf28eb | 33041 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33042 | char buf[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33043 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33044 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33045 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33046 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33047 | d_gettime(&ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33048 | d_localtime(&ret_time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33049 | len = d_tptostr(&tp, buf, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33050 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 33051 | len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33052 | #endif /* V7_ENABLE__Date__toString */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33053 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33054 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33055 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33056 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33058 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33059 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33061 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33062 | #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 33063 | static int d_timetoISOstr(const etime_t *time, char *buf, size_t buf_size) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33064 | /* ISO format: "+XXYYYY-MM-DDTHH:mm:ss.sssZ"; */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33065 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33066 | char use_ext = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33067 | const char *ey_frm = "%06d-%02d-%02dT%02d:%02d:%02d.%03dZ"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33068 | const char *simpl_frm = "%d-%02d-%02dT%02d:%02d:%02d.%03dZ"; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33069 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33070 | d_gmtime(time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33071 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33072 | if (abs(tp.year) > 9999 || tp.year < 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33073 | *buf = (tp.year > 0) ? '+' : '-'; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33074 | use_ext = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33075 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33076 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33077 | return c_snprintf(buf + use_ext, buf_size - use_ext, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33078 | use_ext ? ey_frm : simpl_frm, abs(tp.year), tp.month + 1, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33079 | tp.day, tp.hour, tp.min, tp.sec, tp.msec) + |
Marko Mikulicic |
0:c0ecb8bf28eb | 33080 | use_ext; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33081 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33082 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33083 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33084 | V7_PRIVATE enum v7_err Date_toISOString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33085 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33086 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33087 | char buf[30]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33088 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33089 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33090 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33091 | if (val_type(v7, this_obj) != V7_TYPE_DATE_OBJECT) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33092 | rcode = v7_throwf(v7, TYPE_ERROR, "This is not a Date object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33093 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33094 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33095 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33096 | time = v7_get_double(v7, d_trytogetobjforstring(v7, this_obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33097 | len = d_timetoISOstr(&time, buf, sizeof(buf)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33098 | if (len > (int) (sizeof(buf) - 1 /*null-term*/)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33099 | len = (int) (sizeof(buf) - 1 /*null-term*/); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33100 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33102 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33103 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33104 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33105 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33106 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33107 | #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33108 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33109 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33110 | typedef int (*ftostring_t)(const struct timeparts *, char *, int); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33111 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33112 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33113 | static enum v7_err d_tostring(struct v7 *v7, val_t obj, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33114 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33115 | ftostring_t tostringfunc, int addtz, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33116 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33117 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33118 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33119 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33120 | char buf[100]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33121 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33122 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33123 | time = v7_get_double(v7, d_trytogetobjforstring(v7, obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33124 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33125 | breaktimefunc(&time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33126 | len = tostringfunc(&tp, buf, addtz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33128 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33129 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33130 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33131 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33132 | /* using macros to avoid copy-paste technic */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33133 | #define DEF_TOSTR(funcname, breaktimefunc, tostrfunc, addtz) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33134 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33135 | V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33136 | val_t this_obj = v7_get_this(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33137 | return d_tostring(v7, this_obj, breaktimefunc, tostrfunc, addtz, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33138 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33139 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33140 | /* non-locale function should always return in english and 24h-format */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33141 | static const char *wday_name[] = {"Sun", "Mon", "Tue", "Wed", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33142 | "Thu", "Fri", "Sat"}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33143 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33144 | static int d_tptodatestr(const struct timeparts *tp, char *buf, int addtz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33145 | (void) addtz; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33146 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33147 | return sprintf(buf, "%s %s %02d %d", wday_name[tp->dayofweek], |
Marko Mikulicic |
0:c0ecb8bf28eb | 33148 | mon_name[tp->month], tp->day, tp->year); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33149 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33150 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33151 | DEF_TOSTR(DateString, d_localtime, d_tptodatestr, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33152 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33153 | static const char *d_gettzname(void) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33154 | return g_tzname; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33155 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33156 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33157 | static int d_tptotimestr(const struct timeparts *tp, char *buf, int addtz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33158 | int len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33160 | len = sprintf(buf, "%02d:%02d:%02d GMT", tp->hour, tp->min, tp->sec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33161 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33162 | if (addtz && g_gmtoffms != 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33163 | len = sprintf(buf + len, "%c%02d00 (%s)", g_gmtoffms > 0 ? '-' : '+', |
Marko Mikulicic |
0:c0ecb8bf28eb | 33164 | abs((int) g_gmtoffms / msPerHour), d_gettzname()); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33165 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33166 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33167 | return (int) strlen(buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33168 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33170 | DEF_TOSTR(TimeString, d_localtime, d_tptotimestr, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33171 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33172 | static int d_tptostr(const struct timeparts *tp, char *buf, int addtz) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33173 | int len = d_tptodatestr(tp, buf, addtz); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33174 | *(buf + len) = ' '; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33175 | return d_tptotimestr(tp, buf + len + 1, addtz) + len + 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33176 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33177 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33178 | DEF_TOSTR(String, d_localtime, d_tptostr, 1) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33179 | DEF_TOSTR(UTCString, d_gmtime, d_tptostr, 0) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33180 | #endif /* V7_ENABLE__Date__toString */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33182 | #if V7_ENABLE__Date__toLocaleString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33183 | struct d_locale { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33184 | char locale[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33185 | }; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33186 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33187 | static void d_getcurrentlocale(struct d_locale *loc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33188 | strcpy(loc->locale, setlocale(LC_TIME, 0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33189 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33190 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33191 | static void d_setlocale(const struct d_locale *loc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33192 | setlocale(LC_TIME, loc ? loc->locale : ""); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33193 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33194 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33195 | /* TODO(alashkin): check portability */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33196 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33197 | static enum v7_err d_tolocalestr(struct v7 *v7, val_t obj, const char *frm, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33198 | v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33199 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33200 | char buf[250]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33201 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33202 | struct tm t; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33203 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33204 | struct d_locale prev_locale; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33205 | struct timeparts tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33206 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33207 | time = v7_get_double(v7, d_trytogetobjforstring(v7, obj)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33208 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33209 | d_getcurrentlocale(&prev_locale); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33210 | d_setlocale(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33211 | d_localtime(&time, &tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33212 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33213 | memset(&t, 0, sizeof(t)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33214 | t.tm_year = tp.year - 1900; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33215 | t.tm_mon = tp.month; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33216 | t.tm_mday = tp.day; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33217 | t.tm_hour = tp.hour; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33218 | t.tm_min = tp.min; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33219 | t.tm_sec = tp.sec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33220 | t.tm_wday = tp.dayofweek; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33221 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33222 | len = strftime(buf, sizeof(buf), frm, &t); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33223 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33224 | d_setlocale(&prev_locale); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33225 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33226 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33227 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33228 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33229 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33230 | #define DEF_TOLOCALESTR(funcname, frm) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33231 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33232 | V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33233 | val_t this_obj = v7_get_this(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33234 | return d_tolocalestr(v7, this_obj, frm, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33235 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33236 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33237 | DEF_TOLOCALESTR(LocaleString, "%c") |
Marko Mikulicic |
0:c0ecb8bf28eb | 33238 | DEF_TOLOCALESTR(LocaleDateString, "%x") |
Marko Mikulicic |
0:c0ecb8bf28eb | 33239 | DEF_TOLOCALESTR(LocaleTimeString, "%X") |
Marko Mikulicic |
0:c0ecb8bf28eb | 33240 | #endif /* V7_ENABLE__Date__toLocaleString */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33241 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33242 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33243 | V7_PRIVATE enum v7_err Date_valueOf(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33244 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33245 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33246 | if (!v7_is_generic_object(this_obj) || |
Marko Mikulicic |
0:c0ecb8bf28eb | 33247 | (v7_is_generic_object(this_obj) && |
Marko Mikulicic |
0:c0ecb8bf28eb | 33248 | v7_get_proto(v7, this_obj) != v7->vals.date_prototype)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33249 | rcode = v7_throwf(v7, TYPE_ERROR, "Date.valueOf called on non-Date object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33250 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33251 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33252 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33253 | rcode = Obj_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33254 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33255 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33256 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33257 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33258 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33259 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33260 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33261 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33262 | #if V7_ENABLE__Date__getters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33263 | static struct timeparts *d_getTimePart(struct v7 *v7, val_t val, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33264 | struct timeparts *tp, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33265 | fbreaktime_t breaktimefunc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33266 | etime_t time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33267 | time = v7_get_double(v7, val); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33268 | breaktimefunc(&time, tp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33269 | return tp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33270 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33271 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33272 | #define DEF_GET_TP_FUNC(funcName, tpmember, breaktimefunc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33273 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33274 | V7_PRIVATE enum v7_err Date_get##funcName(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33275 | enum v7_err rcode = V7_OK; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33276 | val_t v = V7_UNDEFINED; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33277 | struct timeparts tp; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33278 | val_t this_obj = v7_get_this(v7); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33279 | \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33280 | rcode = obj_value_of(v7, this_obj, &v); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33281 | if (rcode != V7_OK) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33282 | goto clean; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33283 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33284 | *res = v7_mk_number( \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33285 | v7, v == V7_TAG_NAN ? NAN : d_getTimePart(v7, v, &tp, breaktimefunc) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33286 | ->tpmember); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33287 | clean: \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33288 | return rcode; \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33289 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33290 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33291 | #define DEF_GET_TP(funcName, tpmember) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33292 | DEF_GET_TP_FUNC(UTC##funcName, tpmember, d_gmtime) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33293 | DEF_GET_TP_FUNC(funcName, tpmember, d_localtime) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33294 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33295 | DEF_GET_TP(Date, day) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33296 | DEF_GET_TP(FullYear, year) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33297 | DEF_GET_TP(Month, month) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33298 | DEF_GET_TP(Hours, hour) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33299 | DEF_GET_TP(Minutes, min) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33300 | DEF_GET_TP(Seconds, sec) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33301 | DEF_GET_TP(Milliseconds, msec) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33302 | DEF_GET_TP(Day, dayofweek) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33303 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33304 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33305 | V7_PRIVATE enum v7_err Date_getTime(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33306 | return Date_valueOf(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33307 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33309 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33310 | V7_PRIVATE enum v7_err Date_getTimezoneOffset(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33311 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33312 | *res = v7_mk_number(v7, g_gmtoffms / msPerMinute); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33313 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33314 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33315 | #endif /* V7_ENABLE__Date__getters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33316 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33317 | #if V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33318 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33319 | static enum v7_err d_setTimePart(struct v7 *v7, int start_pos, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33320 | fbreaktime_t breaktimefunc, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33321 | fmaketime_t maketimefunc, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33322 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33323 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33324 | etime_t ret_time = |
Marko Mikulicic |
0:c0ecb8bf28eb | 33325 | d_time_number_from_arr(v7, start_pos, breaktimefunc, maketimefunc); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33326 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33327 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33328 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33329 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33330 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33331 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33332 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33333 | #define DEF_SET_TP(name, start_pos) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33334 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33335 | V7_PRIVATE enum v7_err Date_setUTC##name(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33336 | return d_setTimePart(v7, start_pos, d_gmtime, d_gmktime, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33337 | } \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33338 | WARN_UNUSED_RESULT \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33339 | V7_PRIVATE enum v7_err Date_set##name(struct v7 *v7, v7_val_t *res) { \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33340 | return d_setTimePart(v7, start_pos, d_localtime, d_lmktime, res); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33341 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33342 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33343 | DEF_SET_TP(Milliseconds, tpmsec) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33344 | DEF_SET_TP(Seconds, tpseconds) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33345 | DEF_SET_TP(Minutes, tpminutes) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33346 | DEF_SET_TP(Hours, tphours) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33347 | DEF_SET_TP(Date, tpdate) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33348 | DEF_SET_TP(Month, tpmonth) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33349 | DEF_SET_TP(FullYear, tpyear) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33350 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33351 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33352 | V7_PRIVATE enum v7_err Date_setTime(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33353 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33354 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33355 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33356 | if (v7_argc(v7) >= 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33357 | rcode = to_number_v(v7, v7_arg(v7, 0), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33358 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33359 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33360 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33361 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33362 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33363 | v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33365 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33366 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33367 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33368 | #endif /* V7_ENABLE__Date__setters */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33369 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33370 | #if V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 33371 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33372 | V7_PRIVATE enum v7_err Date_toJSON(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33373 | return Date_toISOString(v7, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33374 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33375 | #endif /* V7_ENABLE__Date__toJSON */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33377 | #if V7_ENABLE__Date__now |
Marko Mikulicic |
0:c0ecb8bf28eb | 33378 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33379 | V7_PRIVATE enum v7_err Date_now(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33380 | etime_t ret_time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33381 | (void) v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33382 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33383 | d_gettime(&ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33384 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33385 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33386 | return V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33387 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33388 | #endif /* V7_ENABLE__Date__now */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33389 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33390 | #if V7_ENABLE__Date__parse |
Marko Mikulicic |
0:c0ecb8bf28eb | 33391 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33392 | V7_PRIVATE enum v7_err Date_parse(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33393 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33394 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33395 | etime_t ret_time = INVALID_TIME; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33396 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33397 | if (!d_iscalledasfunction(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33398 | rcode = v7_throwf(v7, TYPE_ERROR, "Date.parse() called on object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33399 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33400 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33401 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33402 | if (v7_argc(v7) >= 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33403 | val_t arg0 = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33404 | if (v7_is_string(arg0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33405 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33406 | const char *time_str = v7_get_string(v7, &arg0, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33407 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33408 | d_timeFromString(&ret_time, time_str, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33409 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33410 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33411 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33412 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33413 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33414 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33415 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33416 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33417 | #endif /* V7_ENABLE__Date__parse */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33418 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33419 | #if V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 33420 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33421 | V7_PRIVATE enum v7_err Date_UTC(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33422 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33423 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33424 | etime_t ret_time; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33425 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33426 | if (!d_iscalledasfunction(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33427 | rcode = v7_throwf(v7, TYPE_ERROR, "Date.now() called on object"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33428 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33429 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33430 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33431 | ret_time = d_time_number_from_arr(v7, tpyear, 0, d_gmktime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33432 | *res = v7_mk_number(v7, ret_time); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33433 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33434 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33435 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33436 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33437 | #endif /* V7_ENABLE__Date__UTC */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33438 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33439 | /****** Initialization *******/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33440 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33441 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33442 | * We should clear V7_PROPERTY_ENUMERABLE for all Date props |
Marko Mikulicic |
0:c0ecb8bf28eb | 33443 | * TODO(mkm): check other objects |
Marko Mikulicic |
0:c0ecb8bf28eb | 33444 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33445 | static int d_set_cfunc_prop(struct v7 *v7, val_t o, const char *name, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33446 | v7_cfunction_t *f) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33447 | return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33448 | v7_mk_cfunction(f)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33449 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33450 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33451 | #define DECLARE_GET(func) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33452 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "getUTC" #func, \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33453 | Date_getUTC##func); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33454 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "get" #func, Date_get##func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33455 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33456 | #define DECLARE_SET(func) \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33457 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "setUTC" #func, \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33458 | Date_setUTC##func); \ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33459 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "set" #func, Date_set##func); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33460 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33461 | V7_PRIVATE void init_date(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33462 | val_t date = |
Marko Mikulicic |
0:c0ecb8bf28eb | 33463 | mk_cfunction_obj_with_proto(v7, Date_ctor, 7, v7->vals.date_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33464 | v7_def(v7, v7->vals.global_object, "Date", 4, V7_DESC_ENUMERABLE(0), date); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33465 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "valueOf", Date_valueOf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33466 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33467 | #if V7_ENABLE__Date__getters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33468 | DECLARE_GET(Date); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33469 | DECLARE_GET(FullYear); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33470 | DECLARE_GET(Month); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33471 | DECLARE_GET(Hours); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33472 | DECLARE_GET(Minutes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33473 | DECLARE_GET(Seconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33474 | DECLARE_GET(Milliseconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33475 | DECLARE_GET(Day); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33476 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTime", Date_getTime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33477 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33478 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33479 | #if V7_ENABLE__Date__setters |
Marko Mikulicic |
0:c0ecb8bf28eb | 33480 | DECLARE_SET(Date); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33481 | DECLARE_SET(FullYear); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33482 | DECLARE_SET(Month); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33483 | DECLARE_SET(Hours); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33484 | DECLARE_SET(Minutes); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33485 | DECLARE_SET(Seconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33486 | DECLARE_SET(Milliseconds); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33487 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "setTime", Date_setTime); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33488 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTimezoneOffset", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33489 | Date_getTimezoneOffset); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33490 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33491 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33492 | #if V7_ENABLE__Date__now |
Marko Mikulicic |
0:c0ecb8bf28eb | 33493 | d_set_cfunc_prop(v7, date, "now", Date_now); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33494 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33495 | #if V7_ENABLE__Date__parse |
Marko Mikulicic |
0:c0ecb8bf28eb | 33496 | d_set_cfunc_prop(v7, date, "parse", Date_parse); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33497 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33498 | #if V7_ENABLE__Date__UTC |
Marko Mikulicic |
0:c0ecb8bf28eb | 33499 | d_set_cfunc_prop(v7, date, "UTC", Date_UTC); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33500 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33501 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33502 | #if V7_ENABLE__Date__toString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33503 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toString", Date_toString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33504 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toISOString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33505 | Date_toISOString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33506 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toUTCString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33507 | Date_toUTCString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33508 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toDateString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33509 | Date_toDateString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33510 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toTimeString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33511 | Date_toTimeString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33512 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33513 | #if V7_ENABLE__Date__toLocaleString |
Marko Mikulicic |
0:c0ecb8bf28eb | 33514 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33515 | Date_toLocaleString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33516 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleDateString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33517 | Date_toLocaleDateString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33518 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleTimeString", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33519 | Date_toLocaleTimeString); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33520 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33521 | #if V7_ENABLE__Date__toJSON |
Marko Mikulicic |
0:c0ecb8bf28eb | 33522 | d_set_cfunc_prop(v7, v7->vals.date_prototype, "toJSON", Date_toJSON); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33523 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33524 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33525 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33526 | * GTM offset without DST |
Marko Mikulicic |
0:c0ecb8bf28eb | 33527 | * TODO(alashkin): check this |
Marko Mikulicic |
0:c0ecb8bf28eb | 33528 | * Could be changed to tm::tm_gmtoff, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33529 | * but tm_gmtoff includes DST, so |
Marko Mikulicic |
0:c0ecb8bf28eb | 33530 | * side effects are possible |
Marko Mikulicic |
0:c0ecb8bf28eb | 33531 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33532 | tzset(); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33533 | g_gmtoffms = timezone * msPerSecond; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33534 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33535 | * tzname could be changed by localtime_r call, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33536 | * so we have to store pointer |
Marko Mikulicic |
0:c0ecb8bf28eb | 33537 | * TODO(alashkin): need restart on tz change??? |
Marko Mikulicic |
0:c0ecb8bf28eb | 33538 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33539 | g_tzname = tzname[0]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33540 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33541 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33542 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33543 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33544 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33545 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33546 | #endif /* V7_ENABLE__Date */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33547 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 33548 | #line 1 "v7/src/std_function.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 33549 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33550 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33551 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 33552 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 33553 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33554 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33555 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33556 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33557 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33558 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33559 | /* Amalgamated: #include "v7/src/bcode.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33560 | /* Amalgamated: #include "v7/src/eval.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33561 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33562 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33563 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33564 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33565 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33566 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33567 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33568 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33569 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33570 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33571 | V7_PRIVATE enum v7_err Function_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33572 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33573 | long i, num_args = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33574 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33575 | const char *s; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33576 | struct mbuf m; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33577 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33578 | mbuf_init(&m, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33579 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33580 | if (num_args <= 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33581 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33582 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33583 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33584 | mbuf_append(&m, "(function(", 10); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33585 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33586 | for (i = 0; i < num_args - 1; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33587 | rcode = obj_value_of(v7, v7_arg(v7, i), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33588 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33589 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33590 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33591 | if (v7_is_string(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33592 | if (i > 0) mbuf_append(&m, ",", 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33593 | s = v7_get_string(v7, res, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33594 | mbuf_append(&m, s, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33595 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33596 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33597 | mbuf_append(&m, "){", 2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33598 | rcode = obj_value_of(v7, v7_arg(v7, num_args - 1), res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33599 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33600 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33601 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33602 | if (v7_is_string(*res)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33603 | s = v7_get_string(v7, res, &size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33604 | mbuf_append(&m, s, size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33605 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33606 | mbuf_append(&m, "})\0", 3); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33607 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33608 | rcode = v7_exec(v7, m.buf, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33609 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33610 | rcode = v7_throwf(v7, SYNTAX_ERROR, "Invalid function body"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33611 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33612 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33613 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33614 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33615 | mbuf_free(&m); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33616 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33617 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33618 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33619 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33620 | V7_PRIVATE enum v7_err Function_length(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33621 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33622 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33623 | struct v7_js_function *func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33624 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33625 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33626 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33627 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33628 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33629 | if (!is_js_function(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33630 | *res = v7_mk_number(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33631 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33632 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33633 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33634 | func = get_js_function_struct(this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33635 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33636 | *res = v7_mk_number(v7, func->bcode->args_cnt); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33637 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33638 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33639 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33640 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33641 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33642 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33643 | V7_PRIVATE enum v7_err Function_name(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33644 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33645 | v7_val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33646 | struct v7_js_function *func; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33647 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33648 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33649 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33650 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33651 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33652 | if (!is_js_function(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33653 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33654 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33655 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33656 | func = get_js_function_struct(this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33657 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33658 | assert(func->bcode != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33659 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33660 | assert(func->bcode->names_cnt >= 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33661 | bcode_next_name_v(v7, func->bcode, func->bcode->ops.p, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33662 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33663 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33664 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33665 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33666 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33667 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33668 | V7_PRIVATE enum v7_err Function_apply(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33669 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33670 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33671 | val_t this_arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33672 | val_t func_args = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33673 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33674 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33675 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33676 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33677 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33678 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33679 | if (is_js_function(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33680 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33681 | * `Function_apply` is a cfunction, so, GC is inhibited before calling it. |
Marko Mikulicic |
0:c0ecb8bf28eb | 33682 | * But the given function to call is a JS function, so we should enable GC; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33683 | * otherwise, it will be inhibited during the whole execution of the given |
Marko Mikulicic |
0:c0ecb8bf28eb | 33684 | * JS function |
Marko Mikulicic |
0:c0ecb8bf28eb | 33685 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33686 | v7_set_gc_enabled(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33687 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33688 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33689 | rcode = b_apply(v7, this_obj, this_arg, func_args, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33690 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33691 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33692 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33693 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33694 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33695 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33696 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33697 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33698 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33699 | V7_PRIVATE enum v7_err Function_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33700 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33701 | char *ops; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33702 | char *name; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33703 | size_t name_len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33704 | char buf[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33705 | char *b = buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33706 | struct v7_js_function *func = get_js_function_struct(v7_get_this(v7)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33707 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33708 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33709 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "[function"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33710 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33711 | assert(func->bcode != NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33712 | ops = func->bcode->ops.p; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33713 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33714 | /* first entry in name list */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33715 | ops = bcode_next_name(ops, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33716 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33717 | if (name_len > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33718 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), " %.*s", (int) name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33719 | name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33720 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33721 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "("); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33722 | for (i = 0; i < func->bcode->args_cnt; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33723 | ops = bcode_next_name(ops, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33724 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33725 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s", (int) name_len, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33726 | name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33727 | if (i < func->bcode->args_cnt - 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33728 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33729 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33730 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33731 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ")"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33732 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33733 | { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33734 | uint8_t loc_cnt = |
Marko Mikulicic |
0:c0ecb8bf28eb | 33735 | func->bcode->names_cnt - func->bcode->args_cnt - 1 /*func name*/; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33736 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33737 | if (loc_cnt > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33738 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "{var "); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33739 | for (i = 0; i < loc_cnt; ++i) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33740 | ops = bcode_next_name(ops, &name, &name_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33741 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33742 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s", |
Marko Mikulicic |
0:c0ecb8bf28eb | 33743 | (int) name_len, name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33744 | if (i < (loc_cnt - 1)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33745 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ","); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33746 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33747 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33748 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33749 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "}"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33750 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33751 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33752 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33753 | b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "]"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33754 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33755 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33756 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33757 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33758 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33759 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33760 | V7_PRIVATE void init_function(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33761 | val_t ctor = mk_cfunction_obj(v7, Function_ctor, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33762 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33763 | v7_set(v7, ctor, "prototype", 9, v7->vals.function_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33764 | v7_set(v7, v7->vals.global_object, "Function", 8, ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33765 | set_method(v7, v7->vals.function_prototype, "apply", Function_apply, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33766 | set_method(v7, v7->vals.function_prototype, "toString", Function_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33767 | v7_def(v7, v7->vals.function_prototype, "length", 6, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33768 | (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33769 | v7_mk_cfunction(Function_length)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33770 | v7_def(v7, v7->vals.function_prototype, "name", 4, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33771 | (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)), |
Marko Mikulicic |
0:c0ecb8bf28eb | 33772 | v7_mk_cfunction(Function_name)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33773 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33774 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33775 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 33776 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33777 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33778 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 33779 | #line 1 "v7/src/std_regex.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 33780 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 33781 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 33782 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 33783 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 33784 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33785 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33786 | /* Amalgamated: #include "common/utf.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33787 | /* Amalgamated: #include "common/str_util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33788 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33789 | /* Amalgamated: #include "v7/src/std_regex.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33790 | /* Amalgamated: #include "v7/src/std_string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33791 | /* Amalgamated: #include "v7/src/slre.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33792 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33793 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33794 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33795 | /* Amalgamated: #include "v7/src/array.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33796 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33797 | /* Amalgamated: #include "v7/src/regexp.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33798 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33799 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33800 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33801 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33802 | #if V7_ENABLE__RegExp |
Marko Mikulicic |
0:c0ecb8bf28eb | 33803 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33804 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33805 | V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33806 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33807 | long argnum = v7_argc(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33808 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33809 | if (argnum > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33810 | val_t arg = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33811 | val_t ro, fl; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33812 | size_t re_len, flags_len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33813 | const char *re, *flags = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33814 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33815 | if (v7_is_regexp(v7, arg)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33816 | if (argnum > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33817 | /* ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 33818 | rcode = v7_throwf(v7, TYPE_ERROR, "invalid flags"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33819 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33820 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33821 | *res = arg; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33822 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33823 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33824 | rcode = to_string(v7, arg, &ro, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33825 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33826 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33827 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33828 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33829 | if (argnum > 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33830 | rcode = to_string(v7, v7_arg(v7, 1), &fl, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33831 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33832 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33833 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33834 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33835 | flags = v7_get_string(v7, &fl, &flags_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33836 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33837 | re = v7_get_string(v7, &ro, &re_len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33838 | rcode = v7_mk_regexp(v7, re, re_len, flags, flags_len, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33839 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33840 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33841 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33842 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33843 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33844 | rcode = v7_mk_regexp(v7, "(?:)", 4, NULL, 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33845 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33846 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33847 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33848 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33849 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33850 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33851 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33852 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33853 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33854 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33855 | V7_PRIVATE enum v7_err Regex_global(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33856 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33857 | int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33858 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33859 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33860 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33861 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33862 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33863 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33864 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33865 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33866 | flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33867 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33868 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33869 | *res = v7_mk_boolean(v7, flags & SLRE_FLAG_G); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33870 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33871 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33872 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33873 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33874 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33875 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33876 | V7_PRIVATE enum v7_err Regex_ignoreCase(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33877 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33878 | int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33879 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33880 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33881 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33882 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33883 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33884 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33885 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33886 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33887 | flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33888 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33889 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33890 | *res = v7_mk_boolean(v7, flags & SLRE_FLAG_I); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33891 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33892 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33893 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33894 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33895 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33896 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33897 | V7_PRIVATE enum v7_err Regex_multiline(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33898 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33899 | int flags = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33900 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33901 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33902 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33903 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33904 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33905 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33906 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33907 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33908 | flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33909 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33910 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33911 | *res = v7_mk_boolean(v7, flags & SLRE_FLAG_M); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33912 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33913 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33914 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33915 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33916 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33917 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33918 | V7_PRIVATE enum v7_err Regex_source(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33919 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33920 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33921 | val_t r = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33922 | const char *buf = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33923 | size_t len = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33924 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33925 | rcode = obj_value_of(v7, this_obj, &r); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33926 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33927 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33928 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33929 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33930 | if (v7_is_regexp(v7, r)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33931 | buf = v7_get_string(v7, &v7_get_regexp_struct(v7, r)->regexp_string, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33932 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33933 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33934 | *res = v7_mk_string(v7, buf, len, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33935 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33936 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33937 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33938 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33939 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33940 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33941 | V7_PRIVATE enum v7_err Regex_get_lastIndex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33942 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33943 | long lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33944 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33945 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33946 | if (v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33947 | lastIndex = v7_get_regexp_struct(v7, this_obj)->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 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33953 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33954 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33955 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33956 | V7_PRIVATE enum v7_err Regex_set_lastIndex(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33957 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33958 | long lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33959 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33960 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33961 | if (v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33962 | rcode = to_long(v7, v7_arg(v7, 0), 0, &lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33963 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33964 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33965 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33966 | v7_get_regexp_struct(v7, this_obj)->lastIndex = lastIndex; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33967 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33968 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33969 | *res = v7_mk_number(v7, lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33970 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33971 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 33972 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33973 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33974 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33975 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 33976 | V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, val_t rx, val_t vstr, int lind, |
Marko Mikulicic |
0:c0ecb8bf28eb | 33977 | val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33978 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33979 | if (v7_is_regexp(v7, rx)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33980 | val_t s = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33981 | size_t len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33982 | struct slre_loot sub; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33983 | struct slre_cap *ptok = sub.caps; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33984 | const char *str = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33985 | const char *end = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33986 | const char *begin = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33987 | struct v7_regexp *rp = v7_get_regexp_struct(v7, rx); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33988 | int flag_g = slre_get_flags(rp->compiled_regexp) & SLRE_FLAG_G; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33989 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33990 | rcode = to_string(v7, vstr, &s, NULL, 0, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33991 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 33992 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33993 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 33994 | str = v7_get_string(v7, &s, &len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 33995 | end = str + len; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33996 | begin = str; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33997 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 33998 | if (rp->lastIndex < 0) rp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 33999 | if (flag_g || lind) begin = utfnshift(str, rp->lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34000 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34001 | if (!slre_exec(rp->compiled_regexp, 0, begin, end, &sub)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34002 | int i; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34003 | val_t arr = v7_mk_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34004 | char *old_mbuf_base = v7->owned_strings.buf; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34005 | ptrdiff_t rel = 0; /* creating strings might relocate the mbuf */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34006 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34007 | for (i = 0; i < sub.num_captures; i++, ptok++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34008 | rel = v7->owned_strings.buf - old_mbuf_base; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34009 | v7_array_push(v7, arr, v7_mk_string(v7, ptok->start + rel, |
Marko Mikulicic |
0:c0ecb8bf28eb | 34010 | ptok->end - ptok->start, 1)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34011 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34012 | if (flag_g) rp->lastIndex = utfnlen(str, sub.caps->end + rel - str); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34013 | v7_def(v7, arr, "index", 5, V7_DESC_WRITABLE(0), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34014 | v7_mk_number(v7, utfnlen(str + rel, sub.caps->start - str))); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34015 | *res = arr; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34016 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34017 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34018 | rp->lastIndex = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34019 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34020 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34021 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34022 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34023 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34024 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34025 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34026 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34027 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34028 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34029 | V7_PRIVATE enum v7_err Regex_exec(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34030 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34031 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34032 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34033 | if (v7_argc(v7) > 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34034 | rcode = rx_exec(v7, this_obj, v7_arg(v7, 0), 0, res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34035 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34036 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34037 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34038 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34039 | *res = V7_NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34040 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34041 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34042 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34043 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34044 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34045 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34046 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34047 | V7_PRIVATE enum v7_err Regex_test(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34048 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34049 | val_t tmp = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34050 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34051 | rcode = Regex_exec(v7, &tmp); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34052 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34053 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34054 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34055 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34056 | *res = v7_mk_boolean(v7, !v7_is_null(tmp)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34057 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34058 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34059 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34060 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34061 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34062 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34063 | V7_PRIVATE enum v7_err Regex_flags(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34064 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34065 | char buf[3] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34066 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34067 | struct v7_regexp *rp = v7_get_regexp_struct(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34068 | size_t n = get_regexp_flags_str(v7, rp, buf); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34069 | *res = v7_mk_string(v7, buf, n, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34070 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34071 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34072 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34073 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34074 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34075 | V7_PRIVATE enum v7_err Regex_toString(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34076 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34077 | size_t n1, n2 = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34078 | char s2[3] = {0}; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34079 | char buf[50]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34080 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34081 | struct v7_regexp *rp; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34082 | const char *s1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34083 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34084 | rcode = obj_value_of(v7, this_obj, &this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34085 | if (rcode != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34086 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34087 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34088 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34089 | if (!v7_is_regexp(v7, this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34090 | rcode = v7_throwf(v7, TYPE_ERROR, "Not a regexp"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34091 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34092 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34093 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34094 | rp = v7_get_regexp_struct(v7, this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34095 | s1 = v7_get_string(v7, &rp->regexp_string, &n1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34096 | n2 = get_regexp_flags_str(v7, rp, s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34097 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34098 | c_snprintf(buf, sizeof(buf), "/%.*s/%.*s", (int) n1, s1, (int) n2, s2); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34099 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34100 | *res = v7_mk_string(v7, buf, strlen(buf), 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34101 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34102 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34103 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34104 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34105 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34106 | V7_PRIVATE void init_regex(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34107 | val_t ctor = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34108 | mk_cfunction_obj_with_proto(v7, Regex_ctor, 1, v7->vals.regexp_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34109 | val_t lastIndex = v7_mk_dense_array(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34110 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34111 | v7_def(v7, v7->vals.global_object, "RegExp", 6, V7_DESC_ENUMERABLE(0), ctor); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34112 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34113 | set_cfunc_prop(v7, v7->vals.regexp_prototype, "exec", Regex_exec); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34114 | set_cfunc_prop(v7, v7->vals.regexp_prototype, "test", Regex_test); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34115 | set_method(v7, v7->vals.regexp_prototype, "toString", Regex_toString, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34116 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34117 | v7_def(v7, v7->vals.regexp_prototype, "global", 6, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34118 | v7_mk_cfunction(Regex_global)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34119 | v7_def(v7, v7->vals.regexp_prototype, "ignoreCase", 10, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34120 | v7_mk_cfunction(Regex_ignoreCase)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34121 | v7_def(v7, v7->vals.regexp_prototype, "multiline", 9, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34122 | v7_mk_cfunction(Regex_multiline)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34123 | v7_def(v7, v7->vals.regexp_prototype, "source", 6, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34124 | v7_mk_cfunction(Regex_source)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34125 | v7_def(v7, v7->vals.regexp_prototype, "flags", 5, V7_DESC_GETTER(1), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34126 | v7_mk_cfunction(Regex_flags)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34127 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34128 | v7_array_set(v7, lastIndex, 0, v7_mk_cfunction(Regex_get_lastIndex)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34129 | v7_array_set(v7, lastIndex, 1, v7_mk_cfunction(Regex_set_lastIndex)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34130 | v7_def(v7, v7->vals.regexp_prototype, "lastIndex", 9, |
Marko Mikulicic |
0:c0ecb8bf28eb | 34131 | (V7_DESC_GETTER(1) | V7_DESC_SETTER(1)), lastIndex); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34132 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34133 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34134 | #endif /* V7_ENABLE__RegExp */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34135 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 34136 | #line 1 "v7/src/std_proxy.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 34137 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34138 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 34139 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 34140 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 34141 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34142 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34143 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34144 | /* Amalgamated: #include "v7/src/std_object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34145 | /* Amalgamated: #include "v7/src/std_proxy.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34146 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34147 | /* Amalgamated: #include "v7/src/core.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34148 | /* Amalgamated: #include "v7/src/function.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34149 | /* Amalgamated: #include "v7/src/object.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34150 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34151 | /* Amalgamated: #include "v7/src/string.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34152 | /* Amalgamated: #include "v7/src/exceptions.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34153 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34154 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34155 | extern "C" { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34156 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34157 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34158 | #if V7_ENABLE__Proxy |
Marko Mikulicic |
0:c0ecb8bf28eb | 34159 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34160 | WARN_UNUSED_RESULT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34161 | V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34162 | enum v7_err rcode = V7_OK; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34163 | val_t this_obj = v7_get_this(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34164 | val_t target_v = v7_arg(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34165 | val_t handler_v = v7_arg(v7, 1); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34166 | struct v7_object *t = NULL; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34167 | v7_prop_attr_desc_t attrs_desc = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34168 | (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34169 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34170 | if (this_obj == v7_get_global(v7) || !v7_is_object(this_obj)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34171 | rcode = v7_throwf(v7, TYPE_ERROR, "Wrong 'this' object for Proxy ctor"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34172 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34173 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34174 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34175 | if (!v7_is_object(target_v) || !v7_is_object(handler_v)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34176 | rcode = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34177 | v7_throwf(v7, TYPE_ERROR, |
Marko Mikulicic |
0:c0ecb8bf28eb | 34178 | "Cannot create proxy with a non-object as target or handler"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34179 | goto clean; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34180 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34181 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34182 | t = get_object_struct(this_obj); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34183 | t->attributes |= V7_OBJ_PROXY; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34184 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34185 | v7_def(v7, this_obj, _V7_PROXY_TARGET_NAME, ~0, attrs_desc, target_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34186 | v7_def(v7, this_obj, _V7_PROXY_HANDLER_NAME, ~0, attrs_desc, handler_v); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34187 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34188 | (void) res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34189 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34190 | clean: |
Marko Mikulicic |
0:c0ecb8bf28eb | 34191 | return rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34192 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34193 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34194 | V7_PRIVATE void init_proxy(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34195 | /*v7_prop_attr_desc_t attrs_desc =*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34196 | /*(V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));*/ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34197 | val_t proxy = |
Marko Mikulicic |
0:c0ecb8bf28eb | 34198 | mk_cfunction_obj_with_proto(v7, Proxy_ctor, 1, v7->vals.proxy_prototype); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34199 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34200 | v7_def(v7, v7->vals.global_object, "Proxy", ~0, V7_DESC_ENUMERABLE(0), proxy); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34201 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34202 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34203 | V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34204 | int ret = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34205 | if (name_len == (size_t) ~0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34206 | name_len = strlen(name); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34207 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34208 | if (name_len == 5 && (memcmp(name, _V7_PROXY_TARGET_NAME, name_len) == 0 || |
Marko Mikulicic |
0:c0ecb8bf28eb | 34209 | memcmp(name, _V7_PROXY_HANDLER_NAME, name_len) == 0)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34210 | ret = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34211 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34212 | return ret; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34213 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34214 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34215 | #endif /* V7_ENABLE__Proxy */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34216 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34217 | #if defined(__cplusplus) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34218 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34219 | #endif /* __cplusplus */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34220 | #ifdef V7_MODULE_LINES |
Marko Mikulicic |
0:c0ecb8bf28eb | 34221 | #line 1 "v7/src/main.c" |
Marko Mikulicic |
0:c0ecb8bf28eb | 34222 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34223 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 34224 | * Copyright (c) 2014 Cesanta Software Limited |
Marko Mikulicic |
0:c0ecb8bf28eb | 34225 | * All rights reserved |
Marko Mikulicic |
0:c0ecb8bf28eb | 34226 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34227 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34228 | /* Amalgamated: #include "v7/src/internal.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34229 | /* Amalgamated: #include "v7/src/gc.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34230 | /* Amalgamated: #include "v7/src/freeze.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34231 | /* Amalgamated: #include "v7/src/main.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34232 | /* Amalgamated: #include "v7/src/primitive.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34233 | /* Amalgamated: #include "v7/src/exec.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34234 | /* Amalgamated: #include "v7/src/util.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34235 | /* Amalgamated: #include "v7/src/conversion.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34236 | /* Amalgamated: #include "common/platform.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34237 | /* Amalgamated: #include "common/cs_file.h" */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34238 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34239 | #if defined(_MSC_VER) && _MSC_VER >= 1800 |
Marko Mikulicic |
0:c0ecb8bf28eb | 34240 | #define fileno _fileno |
Marko Mikulicic |
0:c0ecb8bf28eb | 34241 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34242 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34243 | #ifdef V7_EXE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34244 | #define V7_MAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 34245 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34246 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34247 | #ifdef V7_MAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 34248 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34249 | #include <sys/stat.h> |
Marko Mikulicic |
0:c0ecb8bf28eb | 34250 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34251 | static void show_usage(char *argv[]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34252 | fprintf(stderr, "V7 version %s (c) Cesanta Software, built on %s\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34253 | V7_VERSION, __DATE__); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34254 | fprintf(stderr, "Usage: %s [OPTIONS] js_file ...\n", argv[0]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34255 | fprintf(stderr, "%s\n", "OPTIONS:"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34256 | fprintf(stderr, "%s\n", " -e <expr> execute expression"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34257 | fprintf(stderr, "%s\n", " -t dump generated text AST"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34258 | fprintf(stderr, "%s\n", " -b dump generated binary AST"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34259 | fprintf(stderr, "%s\n", " -c dump compiled binary bcode"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34260 | fprintf(stderr, "%s\n", " -mm dump memory stats"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34261 | fprintf(stderr, "%s\n", " -vo <n> object arena size"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34262 | fprintf(stderr, "%s\n", " -vf <n> function arena size"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34263 | fprintf(stderr, "%s\n", " -vp <n> property arena size"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34264 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34265 | fprintf(stderr, "%s\n", " -freeze filename dump JS heap into a file"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34266 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34267 | exit(EXIT_FAILURE); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34268 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34269 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34270 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 34271 | static void dump_mm_arena_stats(const char *msg, struct gc_arena *a) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34272 | printf("%s: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34273 | ", alive %lu\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34274 | msg, a->allocations, a->garbage, gc_arena_size(a), a->alive); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34275 | printf( |
Marko Mikulicic |
0:c0ecb8bf28eb | 34276 | "%s: (bytes: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT |
Marko Mikulicic |
0:c0ecb8bf28eb | 34277 | ", alive %lu)\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34278 | msg, a->allocations * a->cell_size, a->garbage * a->cell_size, |
Marko Mikulicic |
0:c0ecb8bf28eb | 34279 | gc_arena_size(a) * a->cell_size, a->alive * a->cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34280 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34281 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34282 | static void dump_mm_stats(struct v7 *v7) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34283 | dump_mm_arena_stats("object: ", &v7->generic_object_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34284 | dump_mm_arena_stats("function: ", &v7->function_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34285 | dump_mm_arena_stats("property: ", &v7->property_arena); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34286 | printf("string arena len: %" SIZE_T_FMT "\n", v7->owned_strings.len); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34287 | printf("Total heap size: %" SIZE_T_FMT "\n", |
Marko Mikulicic |
0:c0ecb8bf28eb | 34288 | v7->owned_strings.len + |
Marko Mikulicic |
0:c0ecb8bf28eb | 34289 | gc_arena_size(&v7->generic_object_arena) * |
Marko Mikulicic |
0:c0ecb8bf28eb | 34290 | v7->generic_object_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 34291 | gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size + |
Marko Mikulicic |
0:c0ecb8bf28eb | 34292 | gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34293 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34294 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34295 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34296 | int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34297 | void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34298 | int exit_rcode = EXIT_SUCCESS; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34299 | struct v7 *v7; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34300 | struct v7_create_opts opts; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34301 | int as_json = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34302 | int i, j, show_ast = 0, binary_ast = 0, dump_bcode = 0, dump_stats = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34303 | val_t res; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34304 | int nexprs = 0; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34305 | const char *exprs[16]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34306 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34307 | memset(&opts, 0, sizeof(opts)); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34308 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34309 | (void) show_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34310 | (void) binary_ast; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34311 | (void) dump_bcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34312 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34313 | /* Execute inline code */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34314 | for (i = 1; i < argc && argv[i][0] == '-'; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34315 | if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34316 | exprs[nexprs++] = argv[i + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34317 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34318 | } else if (strcmp(argv[i], "-t") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34319 | show_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34320 | } else if (strcmp(argv[i], "-b") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34321 | show_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34322 | binary_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34323 | } else if (strcmp(argv[i], "-c") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34324 | binary_ast = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34325 | dump_bcode = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34326 | } else if (strcmp(argv[i], "-h") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34327 | show_usage(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34328 | } else if (strcmp(argv[i], "-j") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34329 | as_json = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34330 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 34331 | } else if (strcmp(argv[i], "-mm") == 0) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34332 | dump_stats = 1; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34333 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34334 | } else if (strcmp(argv[i], "-vo") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34335 | opts.object_arena_size = atoi(argv[i + 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34336 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34337 | } else if (strcmp(argv[i], "-vf") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34338 | opts.function_arena_size = atoi(argv[i + 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34339 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34340 | } else if (strcmp(argv[i], "-vp") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34341 | opts.property_arena_size = atoi(argv[i + 1]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34342 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34343 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34344 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34345 | else if (strcmp(argv[i], "-freeze") == 0 && i + 1 < argc) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34346 | opts.freeze_file = argv[i + 1]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34347 | i++; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34348 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34349 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34350 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34351 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34352 | #ifndef V7_ALLOW_ARGLESS_MAIN |
Marko Mikulicic |
0:c0ecb8bf28eb | 34353 | if (argc == 1) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34354 | show_usage(argv); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34355 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34356 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34357 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34358 | v7 = v7_create_opt(opts); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34359 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34360 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34361 | if (pre_freeze_init != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34362 | pre_freeze_init(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34363 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34364 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34365 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34366 | /* |
Marko Mikulicic |
0:c0ecb8bf28eb | 34367 | * Skip pre_init if freezing, but still execute cmdline expressions. |
Marko Mikulicic |
0:c0ecb8bf28eb | 34368 | * This makes it easier to add custom code when freezing from cmdline. |
Marko Mikulicic |
0:c0ecb8bf28eb | 34369 | */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34370 | if (opts.freeze_file == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34371 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34372 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34373 | if (pre_init != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34374 | pre_init(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34375 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34376 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34377 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34378 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34379 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34380 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34381 | #if V7_ENABLE__Memory__stats > 0 && !defined(V7_DISABLE_GC) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34382 | if (dump_stats) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34383 | printf("Memory stats during init:\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34384 | dump_mm_stats(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34385 | v7_gc(v7, 0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34386 | printf("Memory stats before run:\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34387 | dump_mm_stats(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34388 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34389 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 34390 | (void) dump_stats; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34391 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34392 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34393 | /* Execute inline expressions */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34394 | for (j = 0; j < nexprs; j++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34395 | enum v7_err (*exec)(struct v7 *, const char *, v7_val_t *); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34396 | exec = v7_exec; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34397 | |
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 | if (v7_compile(exprs[j], binary_ast, dump_bcode, stdout) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34401 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34402 | fprintf(stderr, "%s\n", "parse error"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34403 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34404 | #else /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34405 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34406 | fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34407 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34408 | } else if (exec(v7, exprs[j], &res) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34409 | v7_print_error(stderr, v7, exprs[j], res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34410 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34411 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34412 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34413 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34414 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34415 | /* Execute files */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34416 | for (; i < argc; i++) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34417 | if (show_ast || dump_bcode) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34418 | #if !defined(V7_NO_COMPILER) |
Marko Mikulicic |
0:c0ecb8bf28eb | 34419 | size_t size; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34420 | char *source_code; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34421 | if ((source_code = cs_read_file(argv[i], &size)) == NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34422 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34423 | fprintf(stderr, "Cannot read [%s]\n", argv[i]); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34424 | } else { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34425 | if (_v7_compile(source_code, size, binary_ast, dump_bcode, stdout) != |
Marko Mikulicic |
0:c0ecb8bf28eb | 34426 | V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34427 | fprintf(stderr, "error: %s\n", v7->error_msg); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34428 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34429 | exit(exit_rcode); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34430 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34431 | free(source_code); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34432 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34433 | #else /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34434 | exit_rcode = EXIT_FAILURE; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34435 | fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34436 | #endif /* V7_NO_COMPILER */ |
Marko Mikulicic |
0:c0ecb8bf28eb | 34437 | } else if (v7_exec_file(v7, argv[i], &res) != V7_OK) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34438 | v7_print_error(stderr, v7, argv[i], res); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34439 | res = V7_UNDEFINED; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34440 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34441 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34442 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34443 | #ifdef V7_FREEZE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34444 | if (opts.freeze_file != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34445 | freeze(v7, opts.freeze_file); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34446 | exit(0); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34447 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34448 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34449 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34450 | if (!(show_ast || dump_bcode)) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34451 | char buf[2000]; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34452 | char *s = v7_stringify(v7, res, buf, sizeof(buf), |
Marko Mikulicic |
0:c0ecb8bf28eb | 34453 | as_json ? V7_STRINGIFY_JSON : V7_STRINGIFY_DEBUG); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34454 | printf("%s\n", s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34455 | if (s != buf) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34456 | free(s); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34457 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34458 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34459 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34460 | if (post_init != NULL) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34461 | post_init(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34462 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34463 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34464 | #if V7_ENABLE__Memory__stats |
Marko Mikulicic |
0:c0ecb8bf28eb | 34465 | if (dump_stats) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34466 | printf("Memory stats after run:\n"); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34467 | dump_mm_stats(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34468 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34469 | #else |
Marko Mikulicic |
0:c0ecb8bf28eb | 34470 | (void) dump_stats; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34471 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34472 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34473 | v7_destroy(v7); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34474 | return exit_rcode; |
Marko Mikulicic |
0:c0ecb8bf28eb | 34475 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34476 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34477 | |
Marko Mikulicic |
0:c0ecb8bf28eb | 34478 | #ifdef V7_EXE |
Marko Mikulicic |
0:c0ecb8bf28eb | 34479 | int main(int argc, char *argv[]) { |
Marko Mikulicic |
0:c0ecb8bf28eb | 34480 | return v7_main(argc, argv, NULL, NULL, NULL); |
Marko Mikulicic |
0:c0ecb8bf28eb | 34481 | } |
Marko Mikulicic |
0:c0ecb8bf28eb | 34482 | #endif |
Marko Mikulicic |
0:c0ecb8bf28eb | 34483 | #endif /* V7_EXPORT_INTERNAL_HEADERS */ |