Cesanta / v7 Featured

Embedded JavaScript virtual machine

Dependents:   DISCO-F469NI_javascript_blinker

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?

UserRevisionLine numberNew 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(&current_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 */