Cesanta / v7 Featured

Embedded JavaScript virtual machine

Dependents:   DISCO-F469NI_javascript_blinker

Committer:
Marko Mikulicic
Date:
Tue Oct 11 12:22:24 2016 +0200
Revision:
2:7762b98d31c7
Parent:
1:887cf63a2a0b
Child:
3:2bce515c5f0b
Make v7 cpp-safe

Who changed what in which revision?

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 0:c0ecb8bf28eb 1856 #line 1 "v7/src/internal.h"
Marko Mikulicic 0:c0ecb8bf28eb 1857 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1858 /*
Marko Mikulicic 0:c0ecb8bf28eb 1859 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1860 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1861 */
Marko Mikulicic 0:c0ecb8bf28eb 1862
Marko Mikulicic 0:c0ecb8bf28eb 1863 #ifndef CS_V7_SRC_INTERNAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 1864 #define CS_V7_SRC_INTERNAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 1865
Marko Mikulicic 0:c0ecb8bf28eb 1866 /* Amalgamated: #include "v7/src/license.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1867
Marko Mikulicic 0:c0ecb8bf28eb 1868 /* Check whether we're compiling in an environment with no filesystem */
Marko Mikulicic 0:c0ecb8bf28eb 1869 #if defined(ARDUINO) && (ARDUINO == 106)
Marko Mikulicic 0:c0ecb8bf28eb 1870 #define V7_NO_FS
Marko Mikulicic 0:c0ecb8bf28eb 1871 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1872
Marko Mikulicic 0:c0ecb8bf28eb 1873 #ifndef FAST
Marko Mikulicic 0:c0ecb8bf28eb 1874 #define FAST
Marko Mikulicic 0:c0ecb8bf28eb 1875 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1876
Marko Mikulicic 0:c0ecb8bf28eb 1877 #ifndef STATIC
Marko Mikulicic 0:c0ecb8bf28eb 1878 #define STATIC
Marko Mikulicic 0:c0ecb8bf28eb 1879 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1880
Marko Mikulicic 0:c0ecb8bf28eb 1881 #ifndef ENDL
Marko Mikulicic 0:c0ecb8bf28eb 1882 #define ENDL "\n"
Marko Mikulicic 0:c0ecb8bf28eb 1883 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1884
Marko Mikulicic 0:c0ecb8bf28eb 1885 /*
Marko Mikulicic 0:c0ecb8bf28eb 1886 * In some compilers (watcom) NAN == NAN (and other comparisons) don't follow
Marko Mikulicic 0:c0ecb8bf28eb 1887 * the rules of IEEE 754. Since we don't know a priori which compilers
Marko Mikulicic 0:c0ecb8bf28eb 1888 * will generate correct code, we disable the fallback on selected platforms.
Marko Mikulicic 0:c0ecb8bf28eb 1889 * TODO(mkm): selectively disable on clang/gcc once we test this out.
Marko Mikulicic 0:c0ecb8bf28eb 1890 */
Marko Mikulicic 0:c0ecb8bf28eb 1891 #define V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 1892
Marko Mikulicic 0:c0ecb8bf28eb 1893 #undef _POSIX_C_SOURCE
Marko Mikulicic 0:c0ecb8bf28eb 1894 #define _POSIX_C_SOURCE 200809L
Marko Mikulicic 0:c0ecb8bf28eb 1895
Marko Mikulicic 0:c0ecb8bf28eb 1896 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 1897 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 1898 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 1899 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1900 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 1901 #include <float.h>
Marko Mikulicic 0:c0ecb8bf28eb 1902 #include <limits.h>
Marko Mikulicic 0:c0ecb8bf28eb 1903 #include <math.h>
Marko Mikulicic 0:c0ecb8bf28eb 1904 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 1905 #include <stddef.h>
Marko Mikulicic 0:c0ecb8bf28eb 1906 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 1907 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 1908 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 1909 #include <setjmp.h>
Marko Mikulicic 0:c0ecb8bf28eb 1910
Marko Mikulicic 0:c0ecb8bf28eb 1911 /* Public API. Implemented in api.c */
Marko Mikulicic 0:c0ecb8bf28eb 1912 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1913
Marko Mikulicic 0:c0ecb8bf28eb 1914 #ifdef V7_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 1915 #define vsnprintf _vsnprintf
Marko Mikulicic 0:c0ecb8bf28eb 1916 #define snprintf _snprintf
Marko Mikulicic 0:c0ecb8bf28eb 1917
Marko Mikulicic 0:c0ecb8bf28eb 1918 /* VS2015 Update 1 has ISO C99 `isnan` and `isinf` defined in math.h */
Marko Mikulicic 0:c0ecb8bf28eb 1919 #if _MSC_FULL_VER < 190023506
Marko Mikulicic 0:c0ecb8bf28eb 1920 #define isnan(x) _isnan(x)
Marko Mikulicic 0:c0ecb8bf28eb 1921 #define isinf(x) (!_finite(x))
Marko Mikulicic 0:c0ecb8bf28eb 1922 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1923
Marko Mikulicic 0:c0ecb8bf28eb 1924 #define __unused __pragma(warning(suppress : 4100))
Marko Mikulicic 0:c0ecb8bf28eb 1925 typedef __int64 int64_t;
Marko Mikulicic 0:c0ecb8bf28eb 1926 typedef int int32_t;
Marko Mikulicic 0:c0ecb8bf28eb 1927 typedef unsigned int uint32_t;
Marko Mikulicic 0:c0ecb8bf28eb 1928 typedef unsigned short uint16_t;
Marko Mikulicic 0:c0ecb8bf28eb 1929 typedef unsigned char uint8_t;
Marko Mikulicic 0:c0ecb8bf28eb 1930
Marko Mikulicic 0:c0ecb8bf28eb 1931 /* For 64bit VisualStudio 2010 */
Marko Mikulicic 0:c0ecb8bf28eb 1932 #ifndef _UINTPTR_T_DEFINED
Marko Mikulicic 0:c0ecb8bf28eb 1933 typedef unsigned long uintptr_t;
Marko Mikulicic 0:c0ecb8bf28eb 1934 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1935
Marko Mikulicic 0:c0ecb8bf28eb 1936 #ifndef __func__
Marko Mikulicic 0:c0ecb8bf28eb 1937 #define __func__ ""
Marko Mikulicic 0:c0ecb8bf28eb 1938 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1939
Marko Mikulicic 0:c0ecb8bf28eb 1940 #else
Marko Mikulicic 0:c0ecb8bf28eb 1941 #include <stdint.h>
Marko Mikulicic 0:c0ecb8bf28eb 1942 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1943
Marko Mikulicic 0:c0ecb8bf28eb 1944 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1945
Marko Mikulicic 0:c0ecb8bf28eb 1946 /* MSVC6 doesn't have standard C math constants defined */
Marko Mikulicic 0:c0ecb8bf28eb 1947 #ifndef M_E
Marko Mikulicic 0:c0ecb8bf28eb 1948 #define M_E 2.71828182845904523536028747135266250
Marko Mikulicic 0:c0ecb8bf28eb 1949 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1950
Marko Mikulicic 0:c0ecb8bf28eb 1951 #ifndef M_LOG2E
Marko Mikulicic 0:c0ecb8bf28eb 1952 #define M_LOG2E 1.44269504088896340735992468100189214
Marko Mikulicic 0:c0ecb8bf28eb 1953 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1954
Marko Mikulicic 0:c0ecb8bf28eb 1955 #ifndef M_LOG10E
Marko Mikulicic 0:c0ecb8bf28eb 1956 #define M_LOG10E 0.434294481903251827651128918916605082
Marko Mikulicic 0:c0ecb8bf28eb 1957 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1958
Marko Mikulicic 0:c0ecb8bf28eb 1959 #ifndef M_LN2
Marko Mikulicic 0:c0ecb8bf28eb 1960 #define M_LN2 0.693147180559945309417232121458176568
Marko Mikulicic 0:c0ecb8bf28eb 1961 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1962
Marko Mikulicic 0:c0ecb8bf28eb 1963 #ifndef M_LN10
Marko Mikulicic 0:c0ecb8bf28eb 1964 #define M_LN10 2.30258509299404568401799145468436421
Marko Mikulicic 0:c0ecb8bf28eb 1965 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1966
Marko Mikulicic 0:c0ecb8bf28eb 1967 #ifndef M_PI
Marko Mikulicic 0:c0ecb8bf28eb 1968 #define M_PI 3.14159265358979323846264338327950288
Marko Mikulicic 0:c0ecb8bf28eb 1969 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1970
Marko Mikulicic 0:c0ecb8bf28eb 1971 #ifndef M_SQRT2
Marko Mikulicic 0:c0ecb8bf28eb 1972 #define M_SQRT2 1.41421356237309504880168872420969808
Marko Mikulicic 0:c0ecb8bf28eb 1973 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1974
Marko Mikulicic 0:c0ecb8bf28eb 1975 #ifndef M_SQRT1_2
Marko Mikulicic 0:c0ecb8bf28eb 1976 #define M_SQRT1_2 0.707106781186547524400844362104849039
Marko Mikulicic 0:c0ecb8bf28eb 1977 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1978
Marko Mikulicic 0:c0ecb8bf28eb 1979 #ifndef NAN
Marko Mikulicic 0:c0ecb8bf28eb 1980 extern double _v7_nan;
Marko Mikulicic 0:c0ecb8bf28eb 1981 #define HAS_V7_NAN
Marko Mikulicic 0:c0ecb8bf28eb 1982 #define NAN (_v7_nan)
Marko Mikulicic 0:c0ecb8bf28eb 1983 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1984
Marko Mikulicic 0:c0ecb8bf28eb 1985 #ifndef INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 1986 extern double _v7_infinity;
Marko Mikulicic 0:c0ecb8bf28eb 1987 #define HAS_V7_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 1988 #define INFINITY (_v7_infinity)
Marko Mikulicic 0:c0ecb8bf28eb 1989 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1990
Marko Mikulicic 0:c0ecb8bf28eb 1991 #ifndef EXIT_SUCCESS
Marko Mikulicic 0:c0ecb8bf28eb 1992 #define EXIT_SUCCESS 0
Marko Mikulicic 0:c0ecb8bf28eb 1993 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1994
Marko Mikulicic 0:c0ecb8bf28eb 1995 #ifndef EXIT_FAILURE
Marko Mikulicic 0:c0ecb8bf28eb 1996 #define EXIT_FAILURE 1
Marko Mikulicic 0:c0ecb8bf28eb 1997 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1998
Marko Mikulicic 0:c0ecb8bf28eb 1999 #if defined(V7_ENABLE_GC_CHECK) || defined(V7_STACK_GUARD_MIN_SIZE) || \
Marko Mikulicic 0:c0ecb8bf28eb 2000 defined(V7_ENABLE_STACK_TRACKING) || defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 2001 /* Need to enable GCC/clang instrumentation */
Marko Mikulicic 0:c0ecb8bf28eb 2002 #define V7_CYG_PROFILE_ON
Marko Mikulicic 0:c0ecb8bf28eb 2003 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2004
Marko Mikulicic 0:c0ecb8bf28eb 2005 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 2006 extern struct v7 *v7_head;
Marko Mikulicic 0:c0ecb8bf28eb 2007
Marko Mikulicic 0:c0ecb8bf28eb 2008 #if defined(V7_STACK_GUARD_MIN_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 2009 extern void *v7_sp_limit;
Marko Mikulicic 0:c0ecb8bf28eb 2010 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2011 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2012
Marko Mikulicic 0:c0ecb8bf28eb 2013 #ifndef ARRAY_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 2014 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
Marko Mikulicic 0:c0ecb8bf28eb 2015 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2016
Marko Mikulicic 0:c0ecb8bf28eb 2017 #define V7_STATIC_ASSERT(COND, MSG) \
Marko Mikulicic 0:c0ecb8bf28eb 2018 typedef char static_assertion_##MSG[2 * (!!(COND)) - 1]
Marko Mikulicic 0:c0ecb8bf28eb 2019
Marko Mikulicic 0:c0ecb8bf28eb 2020 #define BUF_LEFT(size, used) (((size_t)(used) < (size)) ? ((size) - (used)) : 0)
Marko Mikulicic 0:c0ecb8bf28eb 2021
Marko Mikulicic 0:c0ecb8bf28eb 2022 #endif /* CS_V7_SRC_INTERNAL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2023 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2024 #line 1 "v7/src/core_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 2025 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2026 /*
Marko Mikulicic 0:c0ecb8bf28eb 2027 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2028 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2029 */
Marko Mikulicic 0:c0ecb8bf28eb 2030
Marko Mikulicic 0:c0ecb8bf28eb 2031 /*
Marko Mikulicic 0:c0ecb8bf28eb 2032 * === Core
Marko Mikulicic 0:c0ecb8bf28eb 2033 */
Marko Mikulicic 0:c0ecb8bf28eb 2034
Marko Mikulicic 0:c0ecb8bf28eb 2035 #ifndef CS_V7_SRC_CORE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2036 #define CS_V7_SRC_CORE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2037
Marko Mikulicic 0:c0ecb8bf28eb 2038 #ifndef _POSIX_C_SOURCE
Marko Mikulicic 0:c0ecb8bf28eb 2039 #define _POSIX_C_SOURCE 200809L
Marko Mikulicic 0:c0ecb8bf28eb 2040 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2041
Marko Mikulicic 0:c0ecb8bf28eb 2042 /* Amalgamated: #include "v7/src/license.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2043 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2044
Marko Mikulicic 0:c0ecb8bf28eb 2045 #include <stddef.h> /* For size_t */
Marko Mikulicic 0:c0ecb8bf28eb 2046 #include <stdio.h> /* For FILE */
Marko Mikulicic 0:c0ecb8bf28eb 2047
Marko Mikulicic 2:7762b98d31c7 2048 #if defined(__cplusplus)
Marko Mikulicic 2:7762b98d31c7 2049 extern "C" {
Marko Mikulicic 2:7762b98d31c7 2050 #endif /* __cplusplus */
Marko Mikulicic 2:7762b98d31c7 2051
Marko Mikulicic 0:c0ecb8bf28eb 2052 /*
Marko Mikulicic 0:c0ecb8bf28eb 2053 * TODO(dfrank) : improve amalgamation, so that we'll be able to include
Marko Mikulicic 0:c0ecb8bf28eb 2054 * files here, and include common/platform.h
Marko Mikulicic 0:c0ecb8bf28eb 2055 *
Marko Mikulicic 0:c0ecb8bf28eb 2056 * For now, copy-pasting `WARN_UNUSED_RESULT` here
Marko Mikulicic 0:c0ecb8bf28eb 2057 */
Marko Mikulicic 0:c0ecb8bf28eb 2058 #ifdef __GNUC__
Marko Mikulicic 0:c0ecb8bf28eb 2059 #define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
Marko Mikulicic 0:c0ecb8bf28eb 2060 #define NOINSTR __attribute__((no_instrument_function))
Marko Mikulicic 0:c0ecb8bf28eb 2061 #else
Marko Mikulicic 0:c0ecb8bf28eb 2062 #define WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 2063 #define NOINSTR
Marko Mikulicic 0:c0ecb8bf28eb 2064 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2065
Marko Mikulicic 0:c0ecb8bf28eb 2066 #define V7_VERSION "1.0"
Marko Mikulicic 0:c0ecb8bf28eb 2067
Marko Mikulicic 0:c0ecb8bf28eb 2068 #if (defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)) || \
Marko Mikulicic 0:c0ecb8bf28eb 2069 (defined(_MSC_VER) && _MSC_VER <= 1200)
Marko Mikulicic 0:c0ecb8bf28eb 2070 #define V7_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 2071 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2072
Marko Mikulicic 0:c0ecb8bf28eb 2073 #ifdef V7_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 2074 typedef unsigned __int64 uint64_t;
Marko Mikulicic 0:c0ecb8bf28eb 2075 #else
Marko Mikulicic 0:c0ecb8bf28eb 2076 #include <inttypes.h>
Marko Mikulicic 0:c0ecb8bf28eb 2077 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2078 /* 64-bit value, used to store JS values */
Marko Mikulicic 0:c0ecb8bf28eb 2079 typedef uint64_t v7_val_t;
Marko Mikulicic 0:c0ecb8bf28eb 2080
Marko Mikulicic 0:c0ecb8bf28eb 2081 /* JavaScript `null` value */
Marko Mikulicic 0:c0ecb8bf28eb 2082 #define V7_NULL ((uint64_t) 0xfffe << 48)
Marko Mikulicic 0:c0ecb8bf28eb 2083
Marko Mikulicic 0:c0ecb8bf28eb 2084 /* JavaScript `undefined` value */
Marko Mikulicic 0:c0ecb8bf28eb 2085 #define V7_UNDEFINED ((uint64_t) 0xfffd << 48)
Marko Mikulicic 0:c0ecb8bf28eb 2086
Marko Mikulicic 0:c0ecb8bf28eb 2087 /* This if-0 is a dirty workaround to force etags to pick `struct v7` */
Marko Mikulicic 0:c0ecb8bf28eb 2088 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 2089 /* Opaque structure. V7 engine context. */
Marko Mikulicic 0:c0ecb8bf28eb 2090 struct v7 {
Marko Mikulicic 0:c0ecb8bf28eb 2091 /* ... */
Marko Mikulicic 0:c0ecb8bf28eb 2092 };
Marko Mikulicic 0:c0ecb8bf28eb 2093 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2094
Marko Mikulicic 0:c0ecb8bf28eb 2095 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 2096
Marko Mikulicic 0:c0ecb8bf28eb 2097 /*
Marko Mikulicic 0:c0ecb8bf28eb 2098 * Code which is returned by some of the v7 functions. If something other than
Marko Mikulicic 0:c0ecb8bf28eb 2099 * `V7_OK` is returned from some function, the caller function typically should
Marko Mikulicic 0:c0ecb8bf28eb 2100 * either immediately cleanup and return the code further, or handle the error.
Marko Mikulicic 0:c0ecb8bf28eb 2101 */
Marko Mikulicic 0:c0ecb8bf28eb 2102 enum v7_err {
Marko Mikulicic 0:c0ecb8bf28eb 2103 V7_OK,
Marko Mikulicic 0:c0ecb8bf28eb 2104 V7_SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 2105 V7_EXEC_EXCEPTION,
Marko Mikulicic 0:c0ecb8bf28eb 2106 V7_AST_TOO_LARGE,
Marko Mikulicic 0:c0ecb8bf28eb 2107 V7_INTERNAL_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 2108 };
Marko Mikulicic 0:c0ecb8bf28eb 2109
Marko Mikulicic 0:c0ecb8bf28eb 2110 /* JavaScript -> C call interface */
Marko Mikulicic 0:c0ecb8bf28eb 2111 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 2112 typedef enum v7_err(v7_cfunction_t)(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 2113
Marko Mikulicic 0:c0ecb8bf28eb 2114 /* Create V7 instance */
Marko Mikulicic 0:c0ecb8bf28eb 2115 struct v7 *v7_create(void);
Marko Mikulicic 0:c0ecb8bf28eb 2116
Marko Mikulicic 0:c0ecb8bf28eb 2117 /*
Marko Mikulicic 0:c0ecb8bf28eb 2118 * Customizations of initial V7 state; used by `v7_create_opt()`.
Marko Mikulicic 0:c0ecb8bf28eb 2119 */
Marko Mikulicic 0:c0ecb8bf28eb 2120 struct v7_create_opts {
Marko Mikulicic 0:c0ecb8bf28eb 2121 size_t object_arena_size;
Marko Mikulicic 0:c0ecb8bf28eb 2122 size_t function_arena_size;
Marko Mikulicic 0:c0ecb8bf28eb 2123 size_t property_arena_size;
Marko Mikulicic 0:c0ecb8bf28eb 2124 #ifdef V7_STACK_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 2125 void *c_stack_base;
Marko Mikulicic 0:c0ecb8bf28eb 2126 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2127 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 2128 /* if not NULL, dump JS heap after init */
Marko Mikulicic 0:c0ecb8bf28eb 2129 char *freeze_file;
Marko Mikulicic 0:c0ecb8bf28eb 2130 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2131 };
Marko Mikulicic 0:c0ecb8bf28eb 2132
Marko Mikulicic 0:c0ecb8bf28eb 2133 /*
Marko Mikulicic 0:c0ecb8bf28eb 2134 * Like `v7_create()`, but allows to customize initial v7 state, see `struct
Marko Mikulicic 0:c0ecb8bf28eb 2135 * v7_create_opts`.
Marko Mikulicic 0:c0ecb8bf28eb 2136 */
Marko Mikulicic 0:c0ecb8bf28eb 2137 struct v7 *v7_create_opt(struct v7_create_opts opts);
Marko Mikulicic 0:c0ecb8bf28eb 2138
Marko Mikulicic 0:c0ecb8bf28eb 2139 /* Destroy V7 instance */
Marko Mikulicic 0:c0ecb8bf28eb 2140 void v7_destroy(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2141
Marko Mikulicic 0:c0ecb8bf28eb 2142 /* Return root level (`global`) object of the given V7 instance. */
Marko Mikulicic 0:c0ecb8bf28eb 2143 v7_val_t v7_get_global(struct v7 *v);
Marko Mikulicic 0:c0ecb8bf28eb 2144
Marko Mikulicic 0:c0ecb8bf28eb 2145 /* Return current `this` object. */
Marko Mikulicic 0:c0ecb8bf28eb 2146 v7_val_t v7_get_this(struct v7 *v);
Marko Mikulicic 0:c0ecb8bf28eb 2147
Marko Mikulicic 0:c0ecb8bf28eb 2148 /* Return current `arguments` array */
Marko Mikulicic 0:c0ecb8bf28eb 2149 v7_val_t v7_get_arguments(struct v7 *v);
Marko Mikulicic 0:c0ecb8bf28eb 2150
Marko Mikulicic 0:c0ecb8bf28eb 2151 /* Return i-th argument */
Marko Mikulicic 0:c0ecb8bf28eb 2152 v7_val_t v7_arg(struct v7 *v, unsigned long i);
Marko Mikulicic 0:c0ecb8bf28eb 2153
Marko Mikulicic 0:c0ecb8bf28eb 2154 /* Return the length of `arguments` */
Marko Mikulicic 0:c0ecb8bf28eb 2155 unsigned long v7_argc(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2156
Marko Mikulicic 0:c0ecb8bf28eb 2157 /*
Marko Mikulicic 0:c0ecb8bf28eb 2158 * Tells the GC about a JS value variable/field owned
Marko Mikulicic 0:c0ecb8bf28eb 2159 * by C code.
Marko Mikulicic 0:c0ecb8bf28eb 2160 *
Marko Mikulicic 0:c0ecb8bf28eb 2161 * User C code should own v7_val_t variables
Marko Mikulicic 0:c0ecb8bf28eb 2162 * if the value's lifetime crosses any invocation
Marko Mikulicic 0:c0ecb8bf28eb 2163 * to the v7 runtime that creates new objects or new
Marko Mikulicic 0:c0ecb8bf28eb 2164 * properties and thus can potentially trigger GC.
Marko Mikulicic 0:c0ecb8bf28eb 2165 *
Marko Mikulicic 0:c0ecb8bf28eb 2166 * The registration of the variable prevents the GC from mistakenly treat
Marko Mikulicic 0:c0ecb8bf28eb 2167 * the object as garbage. The GC might be triggered potentially
Marko Mikulicic 0:c0ecb8bf28eb 2168 * allows the GC to update pointers
Marko Mikulicic 0:c0ecb8bf28eb 2169 *
Marko Mikulicic 0:c0ecb8bf28eb 2170 * User code should also explicitly disown the variables with v7_disown once
Marko Mikulicic 0:c0ecb8bf28eb 2171 * it goes out of scope or the structure containing the v7_val_t field is freed.
Marko Mikulicic 0:c0ecb8bf28eb 2172 *
Marko Mikulicic 0:c0ecb8bf28eb 2173 * Example:
Marko Mikulicic 0:c0ecb8bf28eb 2174 *
Marko Mikulicic 0:c0ecb8bf28eb 2175 * ```
Marko Mikulicic 0:c0ecb8bf28eb 2176 * struct v7_val cb;
Marko Mikulicic 0:c0ecb8bf28eb 2177 * v7_own(v7, &cb);
Marko Mikulicic 0:c0ecb8bf28eb 2178 * cb = v7_array_get(v7, args, 0);
Marko Mikulicic 0:c0ecb8bf28eb 2179 * // do something with cb
Marko Mikulicic 0:c0ecb8bf28eb 2180 * v7_disown(v7, &cb);
Marko Mikulicic 0:c0ecb8bf28eb 2181 * ```
Marko Mikulicic 0:c0ecb8bf28eb 2182 */
Marko Mikulicic 0:c0ecb8bf28eb 2183 void v7_own(struct v7 *v7, v7_val_t *v);
Marko Mikulicic 0:c0ecb8bf28eb 2184
Marko Mikulicic 0:c0ecb8bf28eb 2185 /*
Marko Mikulicic 0:c0ecb8bf28eb 2186 * Returns 1 if value is found, 0 otherwise
Marko Mikulicic 0:c0ecb8bf28eb 2187 */
Marko Mikulicic 0:c0ecb8bf28eb 2188 int v7_disown(struct v7 *v7, v7_val_t *v);
Marko Mikulicic 0:c0ecb8bf28eb 2189
Marko Mikulicic 0:c0ecb8bf28eb 2190 /*
Marko Mikulicic 0:c0ecb8bf28eb 2191 * Enable or disable GC.
Marko Mikulicic 0:c0ecb8bf28eb 2192 *
Marko Mikulicic 0:c0ecb8bf28eb 2193 * Must be called before invoking v7_exec or v7_apply
Marko Mikulicic 0:c0ecb8bf28eb 2194 * from within a cfunction unless you know what you're doing.
Marko Mikulicic 0:c0ecb8bf28eb 2195 *
Marko Mikulicic 0:c0ecb8bf28eb 2196 * GC is disabled during execution of cfunctions in order to simplify
Marko Mikulicic 0:c0ecb8bf28eb 2197 * memory management of simple cfunctions.
Marko Mikulicic 0:c0ecb8bf28eb 2198 * However executing even small snippets of JS code causes a lot of memory
Marko Mikulicic 0:c0ecb8bf28eb 2199 * pressure. Enabling GC solves that but forces you to take care of the
Marko Mikulicic 0:c0ecb8bf28eb 2200 * reachability of your temporary V7 v7_val_t variables, as the GC needs
Marko Mikulicic 0:c0ecb8bf28eb 2201 * to know where they are since objects and strings can be either reclaimed
Marko Mikulicic 0:c0ecb8bf28eb 2202 * or relocated during a GC pass.
Marko Mikulicic 0:c0ecb8bf28eb 2203 */
Marko Mikulicic 0:c0ecb8bf28eb 2204 void v7_set_gc_enabled(struct v7 *v7, int enabled);
Marko Mikulicic 0:c0ecb8bf28eb 2205
Marko Mikulicic 0:c0ecb8bf28eb 2206 /*
Marko Mikulicic 0:c0ecb8bf28eb 2207 * Set an optional C stack limit.
Marko Mikulicic 0:c0ecb8bf28eb 2208 *
Marko Mikulicic 0:c0ecb8bf28eb 2209 * It sets a flag that will cause the interpreter
Marko Mikulicic 0:c0ecb8bf28eb 2210 * to throw an InterruptedError.
Marko Mikulicic 0:c0ecb8bf28eb 2211 * It's safe to call it from signal handlers and ISRs
Marko Mikulicic 0:c0ecb8bf28eb 2212 * on single threaded environments.
Marko Mikulicic 0:c0ecb8bf28eb 2213 */
Marko Mikulicic 0:c0ecb8bf28eb 2214 void v7_interrupt(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2215
Marko Mikulicic 0:c0ecb8bf28eb 2216 /* Returns last parser error message. TODO: rename it to `v7_get_error()` */
Marko Mikulicic 0:c0ecb8bf28eb 2217 const char *v7_get_parser_error(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2218
Marko Mikulicic 0:c0ecb8bf28eb 2219 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 2220 /*
Marko Mikulicic 0:c0ecb8bf28eb 2221 * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 2222 *
Marko Mikulicic 0:c0ecb8bf28eb 2223 * Stack metric id. See `v7_stack_stat()`
Marko Mikulicic 0:c0ecb8bf28eb 2224 */
Marko Mikulicic 0:c0ecb8bf28eb 2225 enum v7_stack_stat_what {
Marko Mikulicic 0:c0ecb8bf28eb 2226 /* max stack size consumed by `i_exec()` */
Marko Mikulicic 0:c0ecb8bf28eb 2227 V7_STACK_STAT_EXEC,
Marko Mikulicic 0:c0ecb8bf28eb 2228 /* max stack size consumed by `parse()` (which is called from `i_exec()`) */
Marko Mikulicic 0:c0ecb8bf28eb 2229 V7_STACK_STAT_PARSER,
Marko Mikulicic 0:c0ecb8bf28eb 2230
Marko Mikulicic 0:c0ecb8bf28eb 2231 V7_STACK_STATS_CNT
Marko Mikulicic 0:c0ecb8bf28eb 2232 };
Marko Mikulicic 0:c0ecb8bf28eb 2233
Marko Mikulicic 0:c0ecb8bf28eb 2234 /*
Marko Mikulicic 0:c0ecb8bf28eb 2235 * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 2236 *
Marko Mikulicic 0:c0ecb8bf28eb 2237 * Returns stack metric specified by the metric id `what`. See
Marko Mikulicic 0:c0ecb8bf28eb 2238 * `v7_stack_stat_clean()`
Marko Mikulicic 0:c0ecb8bf28eb 2239 */
Marko Mikulicic 0:c0ecb8bf28eb 2240 int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what);
Marko Mikulicic 0:c0ecb8bf28eb 2241
Marko Mikulicic 0:c0ecb8bf28eb 2242 /*
Marko Mikulicic 0:c0ecb8bf28eb 2243 * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 2244 *
Marko Mikulicic 0:c0ecb8bf28eb 2245 * Clean all stack statistics gathered so far. See `v7_stack_stat()`
Marko Mikulicic 0:c0ecb8bf28eb 2246 */
Marko Mikulicic 0:c0ecb8bf28eb 2247 void v7_stack_stat_clean(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2248 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2249
Marko Mikulicic 2:7762b98d31c7 2250 #if defined(__cplusplus)
Marko Mikulicic 2:7762b98d31c7 2251 }
Marko Mikulicic 2:7762b98d31c7 2252 #endif /* __cplusplus */
Marko Mikulicic 2:7762b98d31c7 2253
Marko Mikulicic 0:c0ecb8bf28eb 2254 #endif /* CS_V7_SRC_CORE_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2255 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2256 #line 1 "v7/src/std_error.h"
Marko Mikulicic 0:c0ecb8bf28eb 2257 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2258 /*
Marko Mikulicic 0:c0ecb8bf28eb 2259 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2260 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2261 */
Marko Mikulicic 0:c0ecb8bf28eb 2262
Marko Mikulicic 0:c0ecb8bf28eb 2263 #ifndef CS_V7_SRC_STD_ERROR_H_
Marko Mikulicic 0:c0ecb8bf28eb 2264 #define CS_V7_SRC_STD_ERROR_H_
Marko Mikulicic 0:c0ecb8bf28eb 2265
Marko Mikulicic 0:c0ecb8bf28eb 2266 /* Amalgamated: #include "v7/src/license.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2267
Marko Mikulicic 0:c0ecb8bf28eb 2268 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 2269
Marko Mikulicic 0:c0ecb8bf28eb 2270 /*
Marko Mikulicic 0:c0ecb8bf28eb 2271 * JavaScript error types
Marko Mikulicic 0:c0ecb8bf28eb 2272 */
Marko Mikulicic 0:c0ecb8bf28eb 2273 #define TYPE_ERROR "TypeError"
Marko Mikulicic 0:c0ecb8bf28eb 2274 #define SYNTAX_ERROR "SyntaxError"
Marko Mikulicic 0:c0ecb8bf28eb 2275 #define REFERENCE_ERROR "ReferenceError"
Marko Mikulicic 0:c0ecb8bf28eb 2276 #define INTERNAL_ERROR "InternalError"
Marko Mikulicic 0:c0ecb8bf28eb 2277 #define RANGE_ERROR "RangeError"
Marko Mikulicic 0:c0ecb8bf28eb 2278 #define EVAL_ERROR "EvalError"
Marko Mikulicic 0:c0ecb8bf28eb 2279 #define ERROR_CTOR_MAX 6
Marko Mikulicic 0:c0ecb8bf28eb 2280 /*
Marko Mikulicic 0:c0ecb8bf28eb 2281 * TODO(mkm): EvalError is not so important, we should guard it behind
Marko Mikulicic 0:c0ecb8bf28eb 2282 * something like `V7_ENABLE__EvalError`. However doing so makes it hard to
Marko Mikulicic 0:c0ecb8bf28eb 2283 * keep ERROR_CTOR_MAX up to date; perhaps let's find a better way of doing it.
Marko Mikulicic 0:c0ecb8bf28eb 2284 *
Marko Mikulicic 0:c0ecb8bf28eb 2285 * EvalError is useful mostly because we now have ecma tests failing:
Marko Mikulicic 0:c0ecb8bf28eb 2286 *
Marko Mikulicic 0:c0ecb8bf28eb 2287 * 8129 FAIL ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-7-c-iii-24.js (tail -c
Marko Mikulicic 0:c0ecb8bf28eb 2288 * +7600043 tests/ecmac.db|head -c 496): [{"message":"[EvalError] is not
Marko Mikulicic 0:c0ecb8bf28eb 2289 * defined"}]
Marko Mikulicic 0:c0ecb8bf28eb 2290 *
Marko Mikulicic 0:c0ecb8bf28eb 2291 * Those tests are not EvalError specific, and they do test that the exception
Marko Mikulicic 0:c0ecb8bf28eb 2292 * handling machinery works as intended.
Marko Mikulicic 0:c0ecb8bf28eb 2293 */
Marko Mikulicic 0:c0ecb8bf28eb 2294
Marko Mikulicic 0:c0ecb8bf28eb 2295 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2296 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2297 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2298
Marko Mikulicic 0:c0ecb8bf28eb 2299 V7_PRIVATE void init_error(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2300
Marko Mikulicic 0:c0ecb8bf28eb 2301 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2302 }
Marko Mikulicic 0:c0ecb8bf28eb 2303 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2304
Marko Mikulicic 0:c0ecb8bf28eb 2305 #endif /* CS_V7_SRC_STD_ERROR_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2306 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2307 #line 1 "v7/src/mm.h"
Marko Mikulicic 0:c0ecb8bf28eb 2308 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2309 /*
Marko Mikulicic 0:c0ecb8bf28eb 2310 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2311 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2312 */
Marko Mikulicic 0:c0ecb8bf28eb 2313
Marko Mikulicic 0:c0ecb8bf28eb 2314 #ifndef CS_V7_SRC_MM_H_
Marko Mikulicic 0:c0ecb8bf28eb 2315 #define CS_V7_SRC_MM_H_
Marko Mikulicic 0:c0ecb8bf28eb 2316
Marko Mikulicic 0:c0ecb8bf28eb 2317 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2318
Marko Mikulicic 0:c0ecb8bf28eb 2319 typedef void (*gc_cell_destructor_t)(struct v7 *v7, void *);
Marko Mikulicic 0:c0ecb8bf28eb 2320
Marko Mikulicic 0:c0ecb8bf28eb 2321 struct gc_block {
Marko Mikulicic 0:c0ecb8bf28eb 2322 struct gc_block *next;
Marko Mikulicic 0:c0ecb8bf28eb 2323 struct gc_cell *base;
Marko Mikulicic 0:c0ecb8bf28eb 2324 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 2325 };
Marko Mikulicic 0:c0ecb8bf28eb 2326
Marko Mikulicic 0:c0ecb8bf28eb 2327 struct gc_arena {
Marko Mikulicic 0:c0ecb8bf28eb 2328 struct gc_block *blocks;
Marko Mikulicic 0:c0ecb8bf28eb 2329 size_t size_increment;
Marko Mikulicic 0:c0ecb8bf28eb 2330 struct gc_cell *free; /* head of free list */
Marko Mikulicic 0:c0ecb8bf28eb 2331 size_t cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 2332
Marko Mikulicic 0:c0ecb8bf28eb 2333 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 2334 unsigned long allocations; /* cumulative counter of allocations */
Marko Mikulicic 0:c0ecb8bf28eb 2335 unsigned long garbage; /* cumulative counter of garbage */
Marko Mikulicic 0:c0ecb8bf28eb 2336 unsigned long alive; /* number of living cells */
Marko Mikulicic 0:c0ecb8bf28eb 2337 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2338
Marko Mikulicic 0:c0ecb8bf28eb 2339 gc_cell_destructor_t destructor;
Marko Mikulicic 0:c0ecb8bf28eb 2340
Marko Mikulicic 0:c0ecb8bf28eb 2341 int verbose;
Marko Mikulicic 0:c0ecb8bf28eb 2342 const char *name; /* for debugging purposes */
Marko Mikulicic 0:c0ecb8bf28eb 2343 };
Marko Mikulicic 0:c0ecb8bf28eb 2344
Marko Mikulicic 0:c0ecb8bf28eb 2345 #endif /* CS_V7_SRC_MM_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2346 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2347 #line 1 "v7/src/parser.h"
Marko Mikulicic 0:c0ecb8bf28eb 2348 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2349 /*
Marko Mikulicic 0:c0ecb8bf28eb 2350 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2351 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2352 */
Marko Mikulicic 0:c0ecb8bf28eb 2353
Marko Mikulicic 0:c0ecb8bf28eb 2354 #ifndef CS_V7_SRC_PARSER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2355 #define CS_V7_SRC_PARSER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2356
Marko Mikulicic 0:c0ecb8bf28eb 2357 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2358 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2359
Marko Mikulicic 0:c0ecb8bf28eb 2360 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 2361
Marko Mikulicic 0:c0ecb8bf28eb 2362 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 2363 struct ast;
Marko Mikulicic 0:c0ecb8bf28eb 2364
Marko Mikulicic 0:c0ecb8bf28eb 2365 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2366 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2367 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2368
Marko Mikulicic 0:c0ecb8bf28eb 2369 struct v7_pstate {
Marko Mikulicic 0:c0ecb8bf28eb 2370 const char *file_name;
Marko Mikulicic 0:c0ecb8bf28eb 2371 const char *source_code;
Marko Mikulicic 0:c0ecb8bf28eb 2372 const char *pc; /* Current parsing position */
Marko Mikulicic 0:c0ecb8bf28eb 2373 const char *src_end; /* End of source code */
Marko Mikulicic 0:c0ecb8bf28eb 2374 int line_no; /* Line number */
Marko Mikulicic 0:c0ecb8bf28eb 2375 int prev_line_no; /* Line number of previous token */
Marko Mikulicic 0:c0ecb8bf28eb 2376 int inhibit_in; /* True while `in` expressions are inhibited */
Marko Mikulicic 0:c0ecb8bf28eb 2377 int in_function; /* True if in a function */
Marko Mikulicic 0:c0ecb8bf28eb 2378 int in_loop; /* True if in a loop */
Marko Mikulicic 0:c0ecb8bf28eb 2379 int in_switch; /* True if in a switch block */
Marko Mikulicic 0:c0ecb8bf28eb 2380 int in_strict; /* True if in strict mode */
Marko Mikulicic 0:c0ecb8bf28eb 2381 };
Marko Mikulicic 0:c0ecb8bf28eb 2382
Marko Mikulicic 0:c0ecb8bf28eb 2383 V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src,
Marko Mikulicic 0:c0ecb8bf28eb 2384 size_t src_len, int is_json);
Marko Mikulicic 0:c0ecb8bf28eb 2385
Marko Mikulicic 0:c0ecb8bf28eb 2386 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2387 }
Marko Mikulicic 0:c0ecb8bf28eb 2388 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2389
Marko Mikulicic 0:c0ecb8bf28eb 2390 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 2391
Marko Mikulicic 0:c0ecb8bf28eb 2392 #endif /* CS_V7_SRC_PARSER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2393 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2394 #line 1 "v7/src/object_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 2395 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2396 /*
Marko Mikulicic 0:c0ecb8bf28eb 2397 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2398 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2399 */
Marko Mikulicic 0:c0ecb8bf28eb 2400
Marko Mikulicic 0:c0ecb8bf28eb 2401 /*
Marko Mikulicic 0:c0ecb8bf28eb 2402 * === Objects
Marko Mikulicic 0:c0ecb8bf28eb 2403 */
Marko Mikulicic 0:c0ecb8bf28eb 2404
Marko Mikulicic 0:c0ecb8bf28eb 2405 #ifndef CS_V7_SRC_OBJECT_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2406 #define CS_V7_SRC_OBJECT_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2407
Marko Mikulicic 0:c0ecb8bf28eb 2408 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2409
Marko Mikulicic 0:c0ecb8bf28eb 2410 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2411 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2412 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2413
Marko Mikulicic 0:c0ecb8bf28eb 2414 /*
Marko Mikulicic 0:c0ecb8bf28eb 2415 * Property attributes bitmask
Marko Mikulicic 0:c0ecb8bf28eb 2416 */
Marko Mikulicic 0:c0ecb8bf28eb 2417 typedef unsigned short v7_prop_attr_t;
Marko Mikulicic 0:c0ecb8bf28eb 2418 #define V7_PROPERTY_NON_WRITABLE (1 << 0)
Marko Mikulicic 0:c0ecb8bf28eb 2419 #define V7_PROPERTY_NON_ENUMERABLE (1 << 1)
Marko Mikulicic 0:c0ecb8bf28eb 2420 #define V7_PROPERTY_NON_CONFIGURABLE (1 << 2)
Marko Mikulicic 0:c0ecb8bf28eb 2421 #define V7_PROPERTY_GETTER (1 << 3)
Marko Mikulicic 0:c0ecb8bf28eb 2422 #define V7_PROPERTY_SETTER (1 << 4)
Marko Mikulicic 0:c0ecb8bf28eb 2423 #define _V7_PROPERTY_HIDDEN (1 << 5)
Marko Mikulicic 0:c0ecb8bf28eb 2424 /* property not managed by V7 HEAP */
Marko Mikulicic 0:c0ecb8bf28eb 2425 #define _V7_PROPERTY_OFF_HEAP (1 << 6)
Marko Mikulicic 0:c0ecb8bf28eb 2426 /* special property holding user data and destructor cb */
Marko Mikulicic 0:c0ecb8bf28eb 2427 #define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR (1 << 7)
Marko Mikulicic 0:c0ecb8bf28eb 2428 /*
Marko Mikulicic 0:c0ecb8bf28eb 2429 * not a property attribute, but a flag for `v7_def()`. It's here in order to
Marko Mikulicic 0:c0ecb8bf28eb 2430 * keep all offsets in one place
Marko Mikulicic 0:c0ecb8bf28eb 2431 */
Marko Mikulicic 0:c0ecb8bf28eb 2432 #define _V7_DESC_PRESERVE_VALUE (1 << 8)
Marko Mikulicic 0:c0ecb8bf28eb 2433
Marko Mikulicic 0:c0ecb8bf28eb 2434 #define V7_PROP_ATTR_IS_WRITABLE(a) (!(a & V7_PROPERTY_NON_WRITABLE))
Marko Mikulicic 0:c0ecb8bf28eb 2435 #define V7_PROP_ATTR_IS_ENUMERABLE(a) (!(a & V7_PROPERTY_NON_ENUMERABLE))
Marko Mikulicic 0:c0ecb8bf28eb 2436 #define V7_PROP_ATTR_IS_CONFIGURABLE(a) (!(a & V7_PROPERTY_NON_CONFIGURABLE))
Marko Mikulicic 0:c0ecb8bf28eb 2437
Marko Mikulicic 0:c0ecb8bf28eb 2438 /*
Marko Mikulicic 0:c0ecb8bf28eb 2439 * Internal helpers for `V7_DESC_...` macros
Marko Mikulicic 0:c0ecb8bf28eb 2440 */
Marko Mikulicic 0:c0ecb8bf28eb 2441 #define _V7_DESC_SHIFT 16
Marko Mikulicic 0:c0ecb8bf28eb 2442 #define _V7_DESC_MASK ((1 << _V7_DESC_SHIFT) - 1)
Marko Mikulicic 0:c0ecb8bf28eb 2443 #define _V7_MK_DESC(v, n) \
Marko Mikulicic 0:c0ecb8bf28eb 2444 (((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0))
Marko Mikulicic 0:c0ecb8bf28eb 2445 #define _V7_MK_DESC_INV(v, n) _V7_MK_DESC(!(v), (n))
Marko Mikulicic 0:c0ecb8bf28eb 2446
Marko Mikulicic 0:c0ecb8bf28eb 2447 /*
Marko Mikulicic 0:c0ecb8bf28eb 2448 * Property attribute descriptors that may be given to `v7_def()`: for each
Marko Mikulicic 0:c0ecb8bf28eb 2449 * attribute (`v7_prop_attr_t`), there is a corresponding macro, which takes
Marko Mikulicic 0:c0ecb8bf28eb 2450 * param: either 1 (set attribute) or 0 (clear attribute). If some particular
Marko Mikulicic 0:c0ecb8bf28eb 2451 * attribute isn't mentioned at all, it's left unchanged (or default, if the
Marko Mikulicic 0:c0ecb8bf28eb 2452 * property is being created)
Marko Mikulicic 0:c0ecb8bf28eb 2453 *
Marko Mikulicic 0:c0ecb8bf28eb 2454 * There is additional flag: `V7_DESC_PRESERVE_VALUE`. If it is set, the
Marko Mikulicic 0:c0ecb8bf28eb 2455 * property value isn't changed (or set to `undefined` if the property is being
Marko Mikulicic 0:c0ecb8bf28eb 2456 * created)
Marko Mikulicic 0:c0ecb8bf28eb 2457 */
Marko Mikulicic 0:c0ecb8bf28eb 2458 typedef unsigned long v7_prop_attr_desc_t;
Marko Mikulicic 0:c0ecb8bf28eb 2459 #define V7_DESC_WRITABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE)
Marko Mikulicic 0:c0ecb8bf28eb 2460 #define V7_DESC_ENUMERABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE)
Marko Mikulicic 0:c0ecb8bf28eb 2461 #define V7_DESC_CONFIGURABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE)
Marko Mikulicic 0:c0ecb8bf28eb 2462 #define V7_DESC_GETTER(v) _V7_MK_DESC(v, V7_PROPERTY_GETTER)
Marko Mikulicic 0:c0ecb8bf28eb 2463 #define V7_DESC_SETTER(v) _V7_MK_DESC(v, V7_PROPERTY_SETTER)
Marko Mikulicic 0:c0ecb8bf28eb 2464 #define V7_DESC_PRESERVE_VALUE _V7_DESC_PRESERVE_VALUE
Marko Mikulicic 0:c0ecb8bf28eb 2465
Marko Mikulicic 0:c0ecb8bf28eb 2466 #define _V7_DESC_HIDDEN(v) _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN)
Marko Mikulicic 0:c0ecb8bf28eb 2467 #define _V7_DESC_OFF_HEAP(v) _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP)
Marko Mikulicic 0:c0ecb8bf28eb 2468
Marko Mikulicic 0:c0ecb8bf28eb 2469 /* See `v7_set_destructor_cb` */
Marko Mikulicic 0:c0ecb8bf28eb 2470 typedef void(v7_destructor_cb_t)(struct v7 *v7, void *ud);
Marko Mikulicic 0:c0ecb8bf28eb 2471
Marko Mikulicic 0:c0ecb8bf28eb 2472 /* Make an empty object */
Marko Mikulicic 0:c0ecb8bf28eb 2473 v7_val_t v7_mk_object(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2474
Marko Mikulicic 0:c0ecb8bf28eb 2475 /*
Marko Mikulicic 0:c0ecb8bf28eb 2476 * Returns true if the given value is an object or function.
Marko Mikulicic 0:c0ecb8bf28eb 2477 * i.e. it returns true if the value holds properties and can be
Marko Mikulicic 0:c0ecb8bf28eb 2478 * used as argument to `v7_get`, `v7_set` and `v7_def`.
Marko Mikulicic 0:c0ecb8bf28eb 2479 */
Marko Mikulicic 0:c0ecb8bf28eb 2480 int v7_is_object(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 2481
Marko Mikulicic 0:c0ecb8bf28eb 2482 /* Set object's prototype. Return old prototype or undefined on error. */
Marko Mikulicic 0:c0ecb8bf28eb 2483 v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 2484
Marko Mikulicic 0:c0ecb8bf28eb 2485 /* Get object's prototype. */
Marko Mikulicic 0:c0ecb8bf28eb 2486 v7_val_t v7_get_proto(struct v7 *v7, v7_val_t obj);
Marko Mikulicic 0:c0ecb8bf28eb 2487
Marko Mikulicic 0:c0ecb8bf28eb 2488 /*
Marko Mikulicic 0:c0ecb8bf28eb 2489 * Lookup property `name` in object `obj`. If `obj` holds no such property,
Marko Mikulicic 0:c0ecb8bf28eb 2490 * an `undefined` value is returned.
Marko Mikulicic 0:c0ecb8bf28eb 2491 *
Marko Mikulicic 0:c0ecb8bf28eb 2492 * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 2493 * `strlen(name)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 2494 */
Marko Mikulicic 0:c0ecb8bf28eb 2495 v7_val_t v7_get(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
Marko Mikulicic 0:c0ecb8bf28eb 2496
Marko Mikulicic 0:c0ecb8bf28eb 2497 /*
Marko Mikulicic 0:c0ecb8bf28eb 2498 * Like `v7_get()`, but "returns" value through `res` pointer argument.
Marko Mikulicic 0:c0ecb8bf28eb 2499 * `res` must not be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 2500 *
Marko Mikulicic 0:c0ecb8bf28eb 2501 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 2502 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 2503 */
Marko Mikulicic 0:c0ecb8bf28eb 2504 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 2505 enum v7_err v7_get_throwing(struct v7 *v7, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 2506 size_t name_len, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 2507
Marko Mikulicic 0:c0ecb8bf28eb 2508 /*
Marko Mikulicic 0:c0ecb8bf28eb 2509 * Define object property, similar to JavaScript `Object.defineProperty()`.
Marko Mikulicic 0:c0ecb8bf28eb 2510 *
Marko Mikulicic 0:c0ecb8bf28eb 2511 * `name`, `name_len` specify property name, `val` is a property value.
Marko Mikulicic 0:c0ecb8bf28eb 2512 * `attrs_desc` is a set of flags which can affect property's attributes,
Marko Mikulicic 0:c0ecb8bf28eb 2513 * see comment of `v7_prop_attr_desc_t` for details.
Marko Mikulicic 0:c0ecb8bf28eb 2514 *
Marko Mikulicic 0:c0ecb8bf28eb 2515 * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 2516 * `strlen(name)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 2517 *
Marko Mikulicic 0:c0ecb8bf28eb 2518 * Returns non-zero on success, 0 on error (e.g. out of memory).
Marko Mikulicic 0:c0ecb8bf28eb 2519 *
Marko Mikulicic 0:c0ecb8bf28eb 2520 * See also `v7_set()`.
Marko Mikulicic 0:c0ecb8bf28eb 2521 */
Marko Mikulicic 0:c0ecb8bf28eb 2522 int v7_def(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len,
Marko Mikulicic 0:c0ecb8bf28eb 2523 v7_prop_attr_desc_t attrs_desc, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 2524
Marko Mikulicic 0:c0ecb8bf28eb 2525 /*
Marko Mikulicic 0:c0ecb8bf28eb 2526 * Set object property. Behaves just like JavaScript assignment.
Marko Mikulicic 0:c0ecb8bf28eb 2527 *
Marko Mikulicic 0:c0ecb8bf28eb 2528 * See also `v7_def()`.
Marko Mikulicic 0:c0ecb8bf28eb 2529 */
Marko Mikulicic 0:c0ecb8bf28eb 2530 int v7_set(struct v7 *v7, v7_val_t obj, const char *name, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 2531 v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 2532
Marko Mikulicic 0:c0ecb8bf28eb 2533 /*
Marko Mikulicic 0:c0ecb8bf28eb 2534 * A helper function to define object's method backed by a C function `func`.
Marko Mikulicic 0:c0ecb8bf28eb 2535 * `name` must be NUL-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 2536 *
Marko Mikulicic 0:c0ecb8bf28eb 2537 * Return value is the same as for `v7_set()`.
Marko Mikulicic 0:c0ecb8bf28eb 2538 */
Marko Mikulicic 0:c0ecb8bf28eb 2539 int v7_set_method(struct v7 *, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 2540 v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 2541
Marko Mikulicic 0:c0ecb8bf28eb 2542 /*
Marko Mikulicic 0:c0ecb8bf28eb 2543 * Delete own property `name` of the object `obj`. Does not follow the
Marko Mikulicic 0:c0ecb8bf28eb 2544 * prototype chain.
Marko Mikulicic 0:c0ecb8bf28eb 2545 *
Marko Mikulicic 0:c0ecb8bf28eb 2546 * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 2547 * `strlen(name)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 2548 *
Marko Mikulicic 0:c0ecb8bf28eb 2549 * Returns 0 on success, -1 on error.
Marko Mikulicic 0:c0ecb8bf28eb 2550 */
Marko Mikulicic 0:c0ecb8bf28eb 2551 int v7_del(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
Marko Mikulicic 0:c0ecb8bf28eb 2552
Marko Mikulicic 0:c0ecb8bf28eb 2553 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 2554 struct prop_iter_proxy_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 2555 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2556
Marko Mikulicic 0:c0ecb8bf28eb 2557 /*
Marko Mikulicic 0:c0ecb8bf28eb 2558 * Context for property iteration, see `v7_next_prop()`.
Marko Mikulicic 0:c0ecb8bf28eb 2559 *
Marko Mikulicic 0:c0ecb8bf28eb 2560 * Clients should not interpret contents of this structure, it's here merely to
Marko Mikulicic 0:c0ecb8bf28eb 2561 * allow clients to allocate it not from the heap.
Marko Mikulicic 0:c0ecb8bf28eb 2562 */
Marko Mikulicic 0:c0ecb8bf28eb 2563 struct prop_iter_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 2564 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 2565 struct prop_iter_proxy_ctx *proxy_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 2566 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2567 struct v7_property *cur_prop;
Marko Mikulicic 0:c0ecb8bf28eb 2568
Marko Mikulicic 0:c0ecb8bf28eb 2569 unsigned init : 1;
Marko Mikulicic 0:c0ecb8bf28eb 2570 };
Marko Mikulicic 0:c0ecb8bf28eb 2571
Marko Mikulicic 0:c0ecb8bf28eb 2572 /*
Marko Mikulicic 0:c0ecb8bf28eb 2573 * Initialize the property iteration context `ctx`, see `v7_next_prop()` for
Marko Mikulicic 0:c0ecb8bf28eb 2574 * usage example.
Marko Mikulicic 0:c0ecb8bf28eb 2575 */
Marko Mikulicic 0:c0ecb8bf28eb 2576 enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 2577 struct prop_iter_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2578
Marko Mikulicic 0:c0ecb8bf28eb 2579 /*
Marko Mikulicic 0:c0ecb8bf28eb 2580 * Destruct the property iteration context `ctx`, see `v7_next_prop()` for
Marko Mikulicic 0:c0ecb8bf28eb 2581 * usage example
Marko Mikulicic 0:c0ecb8bf28eb 2582 */
Marko Mikulicic 0:c0ecb8bf28eb 2583 void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2584
Marko Mikulicic 0:c0ecb8bf28eb 2585 /*
Marko Mikulicic 0:c0ecb8bf28eb 2586 * Iterate over the `obj`'s properties.
Marko Mikulicic 0:c0ecb8bf28eb 2587 *
Marko Mikulicic 0:c0ecb8bf28eb 2588 * Usage example (here we assume we have some `v7_val_t obj`):
Marko Mikulicic 0:c0ecb8bf28eb 2589 *
Marko Mikulicic 0:c0ecb8bf28eb 2590 * struct prop_iter_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 2591 * v7_val_t name, val;
Marko Mikulicic 0:c0ecb8bf28eb 2592 * v7_prop_attr_t attrs;
Marko Mikulicic 0:c0ecb8bf28eb 2593 *
Marko Mikulicic 0:c0ecb8bf28eb 2594 * v7_init_prop_iter_ctx(v7, obj, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2595 * while (v7_next_prop(v7, &ctx, &name, &val, &attrs)) {
Marko Mikulicic 0:c0ecb8bf28eb 2596 * if (V7_PROP_ATTR_IS_ENUMERABLE(attrs)) continue;
Marko Mikulicic 0:c0ecb8bf28eb 2597 * ...
Marko Mikulicic 0:c0ecb8bf28eb 2598 * }
Marko Mikulicic 0:c0ecb8bf28eb 2599 * v7_destruct_prop_iter_ctx(v7, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2600 *
Marko Mikulicic 0:c0ecb8bf28eb 2601 * As you see, v7_next_prop will iterate through all properties, including
Marko Mikulicic 0:c0ecb8bf28eb 2602 * non-enumerable ones, and it's your responsibility to test the attributes
Marko Mikulicic 0:c0ecb8bf28eb 2603 * with the provided `V7_PROP_ATTR_*` macros and proceed as you see fit.
Marko Mikulicic 0:c0ecb8bf28eb 2604 */
Marko Mikulicic 0:c0ecb8bf28eb 2605 int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name,
Marko Mikulicic 0:c0ecb8bf28eb 2606 v7_val_t *value, v7_prop_attr_t *attrs);
Marko Mikulicic 0:c0ecb8bf28eb 2607
Marko Mikulicic 0:c0ecb8bf28eb 2608 /* Returns true if the object is an instance of a given constructor. */
Marko Mikulicic 0:c0ecb8bf28eb 2609 int v7_is_instanceof(struct v7 *v7, v7_val_t o, const char *c);
Marko Mikulicic 0:c0ecb8bf28eb 2610
Marko Mikulicic 0:c0ecb8bf28eb 2611 /* Returns true if the object is an instance of a given constructor. */
Marko Mikulicic 0:c0ecb8bf28eb 2612 int v7_is_instanceof_v(struct v7 *v7, v7_val_t o, v7_val_t c);
Marko Mikulicic 0:c0ecb8bf28eb 2613
Marko Mikulicic 0:c0ecb8bf28eb 2614 /*
Marko Mikulicic 0:c0ecb8bf28eb 2615 * Associates an opaque C value (anything that can be casted to a `void * )
Marko Mikulicic 0:c0ecb8bf28eb 2616 * with an object.
Marko Mikulicic 0:c0ecb8bf28eb 2617 *
Marko Mikulicic 0:c0ecb8bf28eb 2618 * You can achieve a similar effect by just setting a special property with
Marko Mikulicic 0:c0ecb8bf28eb 2619 * a foreign value (see `v7_mk_foreign`), except user data offers the following
Marko Mikulicic 0:c0ecb8bf28eb 2620 * advantages:
Marko Mikulicic 0:c0ecb8bf28eb 2621 *
Marko Mikulicic 0:c0ecb8bf28eb 2622 * 1. You don't have to come up with some arbitrary "special" property name.
Marko Mikulicic 0:c0ecb8bf28eb 2623 * 2. JS scripts cannot access user data by mistake via property lookup.
Marko Mikulicic 0:c0ecb8bf28eb 2624 * 3. The user data is available to the destructor. When the desctructor is
Marko Mikulicic 0:c0ecb8bf28eb 2625 * invoked you cannot access any of its properties.
Marko Mikulicic 0:c0ecb8bf28eb 2626 * 4. Allows the implementation to use a more compact encoding
Marko Mikulicic 0:c0ecb8bf28eb 2627 *
Marko Mikulicic 0:c0ecb8bf28eb 2628 * Does nothing if `obj` is not a mutable object.
Marko Mikulicic 0:c0ecb8bf28eb 2629 */
Marko Mikulicic 0:c0ecb8bf28eb 2630 void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud);
Marko Mikulicic 0:c0ecb8bf28eb 2631
Marko Mikulicic 0:c0ecb8bf28eb 2632 /*
Marko Mikulicic 0:c0ecb8bf28eb 2633 * Get the opaque user data set with `v7_set_user_data`.
Marko Mikulicic 0:c0ecb8bf28eb 2634 *
Marko Mikulicic 0:c0ecb8bf28eb 2635 * Returns NULL if there is no user data set or if `obj` is not an object.
Marko Mikulicic 0:c0ecb8bf28eb 2636 */
Marko Mikulicic 0:c0ecb8bf28eb 2637 void *v7_get_user_data(struct v7 *v7, v7_val_t obj);
Marko Mikulicic 0:c0ecb8bf28eb 2638
Marko Mikulicic 0:c0ecb8bf28eb 2639 /*
Marko Mikulicic 0:c0ecb8bf28eb 2640 * Register a callback which will be invoked when a given object gets
Marko Mikulicic 0:c0ecb8bf28eb 2641 * reclaimed by the garbage collector.
Marko Mikulicic 0:c0ecb8bf28eb 2642 *
Marko Mikulicic 0:c0ecb8bf28eb 2643 * The callback will be invoked while garbage collection is still in progress
Marko Mikulicic 0:c0ecb8bf28eb 2644 * and hence the internal state of the JS heap is in an undefined state.
Marko Mikulicic 0:c0ecb8bf28eb 2645 *
Marko Mikulicic 0:c0ecb8bf28eb 2646 * The only v7 API which is safe to use in this callback is `v7_disown()`,
Marko Mikulicic 0:c0ecb8bf28eb 2647 * that's why `v7` pointer is given to it. *Calls to any other v7 functions are
Marko Mikulicic 0:c0ecb8bf28eb 2648 * illegal here*.
Marko Mikulicic 0:c0ecb8bf28eb 2649 *
Marko Mikulicic 0:c0ecb8bf28eb 2650 * The intended use case is to reclaim resources allocated by C code.
Marko Mikulicic 0:c0ecb8bf28eb 2651 */
Marko Mikulicic 0:c0ecb8bf28eb 2652 void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d);
Marko Mikulicic 0:c0ecb8bf28eb 2653
Marko Mikulicic 0:c0ecb8bf28eb 2654 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2655 }
Marko Mikulicic 0:c0ecb8bf28eb 2656 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2657
Marko Mikulicic 0:c0ecb8bf28eb 2658 #endif /* CS_V7_SRC_OBJECT_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2659 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2660 #line 1 "v7/src/tokenizer.h"
Marko Mikulicic 0:c0ecb8bf28eb 2661 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2662 /*
Marko Mikulicic 0:c0ecb8bf28eb 2663 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2664 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2665 */
Marko Mikulicic 0:c0ecb8bf28eb 2666
Marko Mikulicic 0:c0ecb8bf28eb 2667 #ifndef CS_V7_SRC_TOKENIZER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2668 #define CS_V7_SRC_TOKENIZER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2669
Marko Mikulicic 0:c0ecb8bf28eb 2670 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2671
Marko Mikulicic 0:c0ecb8bf28eb 2672 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 2673
Marko Mikulicic 0:c0ecb8bf28eb 2674 enum v7_tok {
Marko Mikulicic 0:c0ecb8bf28eb 2675 TOK_END_OF_INPUT,
Marko Mikulicic 0:c0ecb8bf28eb 2676 TOK_NUMBER,
Marko Mikulicic 0:c0ecb8bf28eb 2677 TOK_STRING_LITERAL,
Marko Mikulicic 0:c0ecb8bf28eb 2678 TOK_REGEX_LITERAL,
Marko Mikulicic 0:c0ecb8bf28eb 2679 TOK_IDENTIFIER,
Marko Mikulicic 0:c0ecb8bf28eb 2680
Marko Mikulicic 0:c0ecb8bf28eb 2681 /* Punctuators */
Marko Mikulicic 0:c0ecb8bf28eb 2682 TOK_OPEN_CURLY,
Marko Mikulicic 0:c0ecb8bf28eb 2683 TOK_CLOSE_CURLY,
Marko Mikulicic 0:c0ecb8bf28eb 2684 TOK_OPEN_PAREN,
Marko Mikulicic 0:c0ecb8bf28eb 2685 TOK_CLOSE_PAREN,
Marko Mikulicic 0:c0ecb8bf28eb 2686 TOK_COMMA,
Marko Mikulicic 0:c0ecb8bf28eb 2687 TOK_OPEN_BRACKET,
Marko Mikulicic 0:c0ecb8bf28eb 2688 TOK_CLOSE_BRACKET,
Marko Mikulicic 0:c0ecb8bf28eb 2689 TOK_DOT,
Marko Mikulicic 0:c0ecb8bf28eb 2690 TOK_COLON,
Marko Mikulicic 0:c0ecb8bf28eb 2691 TOK_SEMICOLON,
Marko Mikulicic 0:c0ecb8bf28eb 2692
Marko Mikulicic 0:c0ecb8bf28eb 2693 /* Equality ops, in this order */
Marko Mikulicic 0:c0ecb8bf28eb 2694 TOK_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 2695 TOK_EQ_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 2696 TOK_NE,
Marko Mikulicic 0:c0ecb8bf28eb 2697 TOK_NE_NE,
Marko Mikulicic 0:c0ecb8bf28eb 2698
Marko Mikulicic 0:c0ecb8bf28eb 2699 /* Assigns */
Marko Mikulicic 0:c0ecb8bf28eb 2700 TOK_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2701 TOK_REM_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2702 TOK_MUL_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2703 TOK_DIV_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2704 TOK_XOR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2705 TOK_PLUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2706 TOK_MINUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2707 TOK_OR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2708 TOK_AND_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2709 TOK_LSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2710 TOK_RSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2711 TOK_URSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2712 TOK_AND,
Marko Mikulicic 0:c0ecb8bf28eb 2713 TOK_LOGICAL_OR,
Marko Mikulicic 0:c0ecb8bf28eb 2714 TOK_PLUS,
Marko Mikulicic 0:c0ecb8bf28eb 2715 TOK_MINUS,
Marko Mikulicic 0:c0ecb8bf28eb 2716 TOK_PLUS_PLUS,
Marko Mikulicic 0:c0ecb8bf28eb 2717 TOK_MINUS_MINUS,
Marko Mikulicic 0:c0ecb8bf28eb 2718 TOK_LOGICAL_AND,
Marko Mikulicic 0:c0ecb8bf28eb 2719 TOK_OR,
Marko Mikulicic 0:c0ecb8bf28eb 2720 TOK_QUESTION,
Marko Mikulicic 0:c0ecb8bf28eb 2721 TOK_TILDA,
Marko Mikulicic 0:c0ecb8bf28eb 2722 TOK_REM,
Marko Mikulicic 0:c0ecb8bf28eb 2723 TOK_MUL,
Marko Mikulicic 0:c0ecb8bf28eb 2724 TOK_DIV,
Marko Mikulicic 0:c0ecb8bf28eb 2725 TOK_XOR,
Marko Mikulicic 0:c0ecb8bf28eb 2726
Marko Mikulicic 0:c0ecb8bf28eb 2727 /* Relational ops, must go in this order */
Marko Mikulicic 0:c0ecb8bf28eb 2728 TOK_LE,
Marko Mikulicic 0:c0ecb8bf28eb 2729 TOK_LT,
Marko Mikulicic 0:c0ecb8bf28eb 2730 TOK_GE,
Marko Mikulicic 0:c0ecb8bf28eb 2731 TOK_GT,
Marko Mikulicic 0:c0ecb8bf28eb 2732 TOK_LSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 2733 TOK_RSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 2734 TOK_URSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 2735 TOK_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 2736
Marko Mikulicic 0:c0ecb8bf28eb 2737 /* Keywords. must be in the same order as tokenizer.c::s_keywords array */
Marko Mikulicic 0:c0ecb8bf28eb 2738 TOK_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 2739 TOK_CASE,
Marko Mikulicic 0:c0ecb8bf28eb 2740 TOK_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 2741 TOK_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 2742 TOK_DEBUGGER,
Marko Mikulicic 0:c0ecb8bf28eb 2743 TOK_DEFAULT,
Marko Mikulicic 0:c0ecb8bf28eb 2744 TOK_DELETE,
Marko Mikulicic 0:c0ecb8bf28eb 2745 TOK_DO,
Marko Mikulicic 0:c0ecb8bf28eb 2746 TOK_ELSE,
Marko Mikulicic 0:c0ecb8bf28eb 2747 TOK_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 2748 TOK_FINALLY,
Marko Mikulicic 0:c0ecb8bf28eb 2749 TOK_FOR,
Marko Mikulicic 0:c0ecb8bf28eb 2750 TOK_FUNCTION,
Marko Mikulicic 0:c0ecb8bf28eb 2751 TOK_IF,
Marko Mikulicic 0:c0ecb8bf28eb 2752 TOK_IN,
Marko Mikulicic 0:c0ecb8bf28eb 2753 TOK_INSTANCEOF,
Marko Mikulicic 0:c0ecb8bf28eb 2754 TOK_NEW,
Marko Mikulicic 0:c0ecb8bf28eb 2755 TOK_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 2756 TOK_RETURN,
Marko Mikulicic 0:c0ecb8bf28eb 2757 TOK_SWITCH,
Marko Mikulicic 0:c0ecb8bf28eb 2758 TOK_THIS,
Marko Mikulicic 0:c0ecb8bf28eb 2759 TOK_THROW,
Marko Mikulicic 0:c0ecb8bf28eb 2760 TOK_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 2761 TOK_TRY,
Marko Mikulicic 0:c0ecb8bf28eb 2762 TOK_TYPEOF,
Marko Mikulicic 0:c0ecb8bf28eb 2763 TOK_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 2764 TOK_VOID,
Marko Mikulicic 0:c0ecb8bf28eb 2765 TOK_WHILE,
Marko Mikulicic 0:c0ecb8bf28eb 2766 TOK_WITH,
Marko Mikulicic 0:c0ecb8bf28eb 2767
Marko Mikulicic 0:c0ecb8bf28eb 2768 /* TODO(lsm): process these reserved words too */
Marko Mikulicic 0:c0ecb8bf28eb 2769 TOK_CLASS,
Marko Mikulicic 0:c0ecb8bf28eb 2770 TOK_ENUM,
Marko Mikulicic 0:c0ecb8bf28eb 2771 TOK_EXTENDS,
Marko Mikulicic 0:c0ecb8bf28eb 2772 TOK_SUPER,
Marko Mikulicic 0:c0ecb8bf28eb 2773 TOK_CONST,
Marko Mikulicic 0:c0ecb8bf28eb 2774 TOK_EXPORT,
Marko Mikulicic 0:c0ecb8bf28eb 2775 TOK_IMPORT,
Marko Mikulicic 0:c0ecb8bf28eb 2776 TOK_IMPLEMENTS,
Marko Mikulicic 0:c0ecb8bf28eb 2777 TOK_LET,
Marko Mikulicic 0:c0ecb8bf28eb 2778 TOK_PRIVATE,
Marko Mikulicic 0:c0ecb8bf28eb 2779 TOK_PUBLIC,
Marko Mikulicic 0:c0ecb8bf28eb 2780 TOK_INTERFACE,
Marko Mikulicic 0:c0ecb8bf28eb 2781 TOK_PACKAGE,
Marko Mikulicic 0:c0ecb8bf28eb 2782 TOK_PROTECTED,
Marko Mikulicic 0:c0ecb8bf28eb 2783 TOK_STATIC,
Marko Mikulicic 0:c0ecb8bf28eb 2784 TOK_YIELD,
Marko Mikulicic 0:c0ecb8bf28eb 2785
Marko Mikulicic 0:c0ecb8bf28eb 2786 NUM_TOKENS
Marko Mikulicic 0:c0ecb8bf28eb 2787 };
Marko Mikulicic 0:c0ecb8bf28eb 2788
Marko Mikulicic 0:c0ecb8bf28eb 2789 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2790 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2791 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2792
Marko Mikulicic 0:c0ecb8bf28eb 2793 V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end);
Marko Mikulicic 0:c0ecb8bf28eb 2794 V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n,
Marko Mikulicic 0:c0ecb8bf28eb 2795 enum v7_tok prev_tok);
Marko Mikulicic 0:c0ecb8bf28eb 2796 V7_PRIVATE int is_reserved_word_token(enum v7_tok tok);
Marko Mikulicic 0:c0ecb8bf28eb 2797
Marko Mikulicic 0:c0ecb8bf28eb 2798 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2799 }
Marko Mikulicic 0:c0ecb8bf28eb 2800 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2801
Marko Mikulicic 0:c0ecb8bf28eb 2802 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 2803
Marko Mikulicic 0:c0ecb8bf28eb 2804 #endif /* CS_V7_SRC_TOKENIZER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2805 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2806 #line 1 "v7/src/opcodes.h"
Marko Mikulicic 0:c0ecb8bf28eb 2807 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2808 /*
Marko Mikulicic 0:c0ecb8bf28eb 2809 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2810 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2811 */
Marko Mikulicic 0:c0ecb8bf28eb 2812
Marko Mikulicic 0:c0ecb8bf28eb 2813 #ifndef CS_V7_SRC_OPCODES_H_
Marko Mikulicic 0:c0ecb8bf28eb 2814 #define CS_V7_SRC_OPCODES_H_
Marko Mikulicic 0:c0ecb8bf28eb 2815
Marko Mikulicic 0:c0ecb8bf28eb 2816 /*
Marko Mikulicic 0:c0ecb8bf28eb 2817 * ==== Instructions
Marko Mikulicic 0:c0ecb8bf28eb 2818 *
Marko Mikulicic 0:c0ecb8bf28eb 2819 * Bytecode instructions consist of 1-byte opcode, optionally followed by N
Marko Mikulicic 0:c0ecb8bf28eb 2820 * bytes of arguments.
Marko Mikulicic 0:c0ecb8bf28eb 2821 *
Marko Mikulicic 0:c0ecb8bf28eb 2822 * Opcodes that accept an index in the literal table (PUSH_LIT, GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 2823 * SET_VAR, ...) also accept inline literals. In order to distinguish indices in
Marko Mikulicic 0:c0ecb8bf28eb 2824 * the literals table and the inline literals, indices 0 and 1 are reserved as
Marko Mikulicic 0:c0ecb8bf28eb 2825 * type tags for inline literals:
Marko Mikulicic 0:c0ecb8bf28eb 2826 *
Marko Mikulicic 0:c0ecb8bf28eb 2827 * if 0, the following bytes encode a string literal
Marko Mikulicic 0:c0ecb8bf28eb 2828 * if 1, they encode a number (textual, like in the AST)
Marko Mikulicic 0:c0ecb8bf28eb 2829 *
Marko Mikulicic 0:c0ecb8bf28eb 2830 * (see enum bcode_inline_lit_type_tag)
Marko Mikulicic 0:c0ecb8bf28eb 2831 *
Marko Mikulicic 0:c0ecb8bf28eb 2832 *
Marko Mikulicic 0:c0ecb8bf28eb 2833 * Stack diagrams follow the syntax and semantics of:
Marko Mikulicic 0:c0ecb8bf28eb 2834 *
Marko Mikulicic 0:c0ecb8bf28eb 2835 * http://everything2.com/title/Forth+stack+diagrams[Forth stack diagrams].
Marko Mikulicic 0:c0ecb8bf28eb 2836 *
Marko Mikulicic 0:c0ecb8bf28eb 2837 * We use the following extension in the terminology:
Marko Mikulicic 0:c0ecb8bf28eb 2838 *
Marko Mikulicic 0:c0ecb8bf28eb 2839 * `T`: "Try stack".
Marko Mikulicic 0:c0ecb8bf28eb 2840 * `A`: opcode arguments.
Marko Mikulicic 0:c0ecb8bf28eb 2841 * `S`: stash register (one element stack).
Marko Mikulicic 0:c0ecb8bf28eb 2842 *
Marko Mikulicic 0:c0ecb8bf28eb 2843 */
Marko Mikulicic 0:c0ecb8bf28eb 2844 enum opcode {
Marko Mikulicic 0:c0ecb8bf28eb 2845 /*
Marko Mikulicic 0:c0ecb8bf28eb 2846 * Removes an item from the top of the stack. It is undefined what happens if
Marko Mikulicic 0:c0ecb8bf28eb 2847 * the stack is empty.
Marko Mikulicic 0:c0ecb8bf28eb 2848 *
Marko Mikulicic 0:c0ecb8bf28eb 2849 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 2850 */
Marko Mikulicic 0:c0ecb8bf28eb 2851 OP_DROP,
Marko Mikulicic 0:c0ecb8bf28eb 2852 /*
Marko Mikulicic 0:c0ecb8bf28eb 2853 * Duplicates a value on top of the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2854 *
Marko Mikulicic 0:c0ecb8bf28eb 2855 * `( a -- a a)`
Marko Mikulicic 0:c0ecb8bf28eb 2856 */
Marko Mikulicic 0:c0ecb8bf28eb 2857 OP_DUP,
Marko Mikulicic 0:c0ecb8bf28eb 2858 /*
Marko Mikulicic 0:c0ecb8bf28eb 2859 * Duplicates 2 values from the top of the stack in the same order.
Marko Mikulicic 0:c0ecb8bf28eb 2860 *
Marko Mikulicic 0:c0ecb8bf28eb 2861 * `( a b -- a b a b)`
Marko Mikulicic 0:c0ecb8bf28eb 2862 */
Marko Mikulicic 0:c0ecb8bf28eb 2863 OP_2DUP,
Marko Mikulicic 0:c0ecb8bf28eb 2864 /*
Marko Mikulicic 0:c0ecb8bf28eb 2865 * Swap the top two items on the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2866 *
Marko Mikulicic 0:c0ecb8bf28eb 2867 * `( a b -- b a )`
Marko Mikulicic 0:c0ecb8bf28eb 2868 */
Marko Mikulicic 0:c0ecb8bf28eb 2869 OP_SWAP,
Marko Mikulicic 0:c0ecb8bf28eb 2870 /*
Marko Mikulicic 0:c0ecb8bf28eb 2871 * Copy current top of the stack to the temporary stash register.
Marko Mikulicic 0:c0ecb8bf28eb 2872 *
Marko Mikulicic 0:c0ecb8bf28eb 2873 * The content of the stash register will be cleared in the event of an
Marko Mikulicic 0:c0ecb8bf28eb 2874 * exception.
Marko Mikulicic 0:c0ecb8bf28eb 2875 *
Marko Mikulicic 0:c0ecb8bf28eb 2876 * `( a S: b -- a S: a)` saves TOS to stash reg
Marko Mikulicic 0:c0ecb8bf28eb 2877 */
Marko Mikulicic 0:c0ecb8bf28eb 2878 OP_STASH,
Marko Mikulicic 0:c0ecb8bf28eb 2879 /*
Marko Mikulicic 0:c0ecb8bf28eb 2880 * Replace the top of the stack with the content of the temporary stash
Marko Mikulicic 0:c0ecb8bf28eb 2881 * register.
Marko Mikulicic 0:c0ecb8bf28eb 2882 *
Marko Mikulicic 0:c0ecb8bf28eb 2883 * The stash register is cleared afterwards.
Marko Mikulicic 0:c0ecb8bf28eb 2884 *
Marko Mikulicic 0:c0ecb8bf28eb 2885 * `( a S: b -- b S: nil )` replaces tos with stash reg
Marko Mikulicic 0:c0ecb8bf28eb 2886 */
Marko Mikulicic 0:c0ecb8bf28eb 2887 OP_UNSTASH,
Marko Mikulicic 0:c0ecb8bf28eb 2888
Marko Mikulicic 0:c0ecb8bf28eb 2889 /*
Marko Mikulicic 0:c0ecb8bf28eb 2890 * Effectively drops the last-but-one element from stack
Marko Mikulicic 0:c0ecb8bf28eb 2891 *
Marko Mikulicic 0:c0ecb8bf28eb 2892 * `( a b -- b )`
Marko Mikulicic 0:c0ecb8bf28eb 2893 */
Marko Mikulicic 0:c0ecb8bf28eb 2894 OP_SWAP_DROP,
Marko Mikulicic 0:c0ecb8bf28eb 2895
Marko Mikulicic 0:c0ecb8bf28eb 2896 /*
Marko Mikulicic 0:c0ecb8bf28eb 2897 * Pushes `undefined` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2898 *
Marko Mikulicic 0:c0ecb8bf28eb 2899 * `( -- undefined )`
Marko Mikulicic 0:c0ecb8bf28eb 2900 */
Marko Mikulicic 0:c0ecb8bf28eb 2901 OP_PUSH_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 2902 /*
Marko Mikulicic 0:c0ecb8bf28eb 2903 * Pushes `null` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2904 *
Marko Mikulicic 0:c0ecb8bf28eb 2905 * `( -- null )`
Marko Mikulicic 0:c0ecb8bf28eb 2906 */
Marko Mikulicic 0:c0ecb8bf28eb 2907 OP_PUSH_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 2908 /*
Marko Mikulicic 0:c0ecb8bf28eb 2909 * Pushes current value of `this` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2910 *
Marko Mikulicic 0:c0ecb8bf28eb 2911 * `( -- this )`
Marko Mikulicic 0:c0ecb8bf28eb 2912 */
Marko Mikulicic 0:c0ecb8bf28eb 2913 OP_PUSH_THIS,
Marko Mikulicic 0:c0ecb8bf28eb 2914 /*
Marko Mikulicic 0:c0ecb8bf28eb 2915 * Pushes `true` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2916 *
Marko Mikulicic 0:c0ecb8bf28eb 2917 * `( -- true )`
Marko Mikulicic 0:c0ecb8bf28eb 2918 */
Marko Mikulicic 0:c0ecb8bf28eb 2919 OP_PUSH_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 2920 /*
Marko Mikulicic 0:c0ecb8bf28eb 2921 * Pushes `false` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2922 *
Marko Mikulicic 0:c0ecb8bf28eb 2923 * `( -- false )`
Marko Mikulicic 0:c0ecb8bf28eb 2924 */
Marko Mikulicic 0:c0ecb8bf28eb 2925 OP_PUSH_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 2926 /*
Marko Mikulicic 0:c0ecb8bf28eb 2927 * Pushes `0` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2928 *
Marko Mikulicic 0:c0ecb8bf28eb 2929 * `( -- 0 )`
Marko Mikulicic 0:c0ecb8bf28eb 2930 */
Marko Mikulicic 0:c0ecb8bf28eb 2931 OP_PUSH_ZERO,
Marko Mikulicic 0:c0ecb8bf28eb 2932 /*
Marko Mikulicic 0:c0ecb8bf28eb 2933 * Pushes `1` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2934 *
Marko Mikulicic 0:c0ecb8bf28eb 2935 * `( -- 1 )`
Marko Mikulicic 0:c0ecb8bf28eb 2936 */
Marko Mikulicic 0:c0ecb8bf28eb 2937 OP_PUSH_ONE,
Marko Mikulicic 0:c0ecb8bf28eb 2938
Marko Mikulicic 0:c0ecb8bf28eb 2939 /*
Marko Mikulicic 0:c0ecb8bf28eb 2940 * Pushes a value from literals table onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2941 *
Marko Mikulicic 0:c0ecb8bf28eb 2942 * The opcode takes a varint operand interpreted as an index in the current
Marko Mikulicic 0:c0ecb8bf28eb 2943 * literal table (see lit table).
Marko Mikulicic 0:c0ecb8bf28eb 2944 *
Marko Mikulicic 0:c0ecb8bf28eb 2945 * ( -- a )
Marko Mikulicic 0:c0ecb8bf28eb 2946 */
Marko Mikulicic 0:c0ecb8bf28eb 2947 OP_PUSH_LIT,
Marko Mikulicic 0:c0ecb8bf28eb 2948
Marko Mikulicic 0:c0ecb8bf28eb 2949 OP_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 2950 OP_LOGICAL_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 2951
Marko Mikulicic 0:c0ecb8bf28eb 2952 /*
Marko Mikulicic 0:c0ecb8bf28eb 2953 * Takes a number from the top of the stack, inverts the sign and pushes it
Marko Mikulicic 0:c0ecb8bf28eb 2954 * back.
Marko Mikulicic 0:c0ecb8bf28eb 2955 *
Marko Mikulicic 0:c0ecb8bf28eb 2956 * `( a -- -a )`
Marko Mikulicic 0:c0ecb8bf28eb 2957 */
Marko Mikulicic 0:c0ecb8bf28eb 2958 OP_NEG,
Marko Mikulicic 0:c0ecb8bf28eb 2959 /*
Marko Mikulicic 0:c0ecb8bf28eb 2960 * Takes a number from the top of the stack pushes the evaluation of
Marko Mikulicic 0:c0ecb8bf28eb 2961 * `Number()`.
Marko Mikulicic 0:c0ecb8bf28eb 2962 *
Marko Mikulicic 0:c0ecb8bf28eb 2963 * `( a -- Number(a) )`
Marko Mikulicic 0:c0ecb8bf28eb 2964 */
Marko Mikulicic 0:c0ecb8bf28eb 2965 OP_POS,
Marko Mikulicic 0:c0ecb8bf28eb 2966
Marko Mikulicic 0:c0ecb8bf28eb 2967 /*
Marko Mikulicic 0:c0ecb8bf28eb 2968 * Takes 2 values from the top of the stack and performs addition operation:
Marko Mikulicic 0:c0ecb8bf28eb 2969 * If any of the two values is not `undefined`, number or boolean, both values
Marko Mikulicic 0:c0ecb8bf28eb 2970 * are converted into strings and concatenated.
Marko Mikulicic 0:c0ecb8bf28eb 2971 * Otherwise, both values are treated as numbers:
Marko Mikulicic 0:c0ecb8bf28eb 2972 * * `undefined` is converted into NaN
Marko Mikulicic 0:c0ecb8bf28eb 2973 * * `true` is converted into 1
Marko Mikulicic 0:c0ecb8bf28eb 2974 * * `false` is converted into 0
Marko Mikulicic 0:c0ecb8bf28eb 2975 *
Marko Mikulicic 0:c0ecb8bf28eb 2976 * Result is pushed back onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2977 *
Marko Mikulicic 0:c0ecb8bf28eb 2978 * TODO: make it behave exactly like JavaScript's `+` operator.
Marko Mikulicic 0:c0ecb8bf28eb 2979 *
Marko Mikulicic 0:c0ecb8bf28eb 2980 * `( a b -- a+b )`
Marko Mikulicic 0:c0ecb8bf28eb 2981 */
Marko Mikulicic 0:c0ecb8bf28eb 2982 OP_ADD,
Marko Mikulicic 0:c0ecb8bf28eb 2983 OP_SUB, /* ( a b -- a-b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2984 OP_REM, /* ( a b -- a%b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2985 OP_MUL, /* ( a b -- a*b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2986 OP_DIV, /* ( a b -- a/b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2987 OP_LSHIFT, /* ( a b -- a<<b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2988 OP_RSHIFT, /* ( a b -- a>>b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2989 OP_URSHIFT, /* ( a b -- a>>>b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2990 OP_OR, /* ( a b -- a|b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2991 OP_XOR, /* ( a b -- a^b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2992 OP_AND, /* ( a b -- a&b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2993
Marko Mikulicic 0:c0ecb8bf28eb 2994 /*
Marko Mikulicic 0:c0ecb8bf28eb 2995 * Takes two numbers form the top of the stack and pushes `true` if they are
Marko Mikulicic 0:c0ecb8bf28eb 2996 * equal, or `false` if they are not equal.
Marko Mikulicic 0:c0ecb8bf28eb 2997 *
Marko Mikulicic 0:c0ecb8bf28eb 2998 * ( a b -- a===b )
Marko Mikulicic 0:c0ecb8bf28eb 2999 */
Marko Mikulicic 0:c0ecb8bf28eb 3000 OP_EQ_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 3001 OP_EQ, /* ( a b -- a==b ) */
Marko Mikulicic 0:c0ecb8bf28eb 3002 OP_NE, /* ( a b -- a!=b ) */
Marko Mikulicic 0:c0ecb8bf28eb 3003 OP_NE_NE, /* ( a b -- a!==b ) */
Marko Mikulicic 0:c0ecb8bf28eb 3004 OP_LT, /* ( a b -- a<b ) */
Marko Mikulicic 0:c0ecb8bf28eb 3005 OP_LE, /* ( a b -- a<=b ) */
Marko Mikulicic 0:c0ecb8bf28eb 3006 OP_GT, /* ( a b -- a>b ) */
Marko Mikulicic 0:c0ecb8bf28eb 3007 OP_GE, /* ( a b -- a>=b ) */
Marko Mikulicic 0:c0ecb8bf28eb 3008 OP_INSTANCEOF,
Marko Mikulicic 0:c0ecb8bf28eb 3009
Marko Mikulicic 0:c0ecb8bf28eb 3010 OP_TYPEOF,
Marko Mikulicic 0:c0ecb8bf28eb 3011
Marko Mikulicic 0:c0ecb8bf28eb 3012 OP_IN,
Marko Mikulicic 0:c0ecb8bf28eb 3013 /*
Marko Mikulicic 0:c0ecb8bf28eb 3014 * Takes 2 values from the stack, treats the top of the stack as property name
Marko Mikulicic 0:c0ecb8bf28eb 3015 * and the next value must be an object, an array or a string.
Marko Mikulicic 0:c0ecb8bf28eb 3016 * If it's an object, pushes the value of its named property onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 3017 * If it's an array or a string, returns a value at a given position.
Marko Mikulicic 0:c0ecb8bf28eb 3018 */
Marko Mikulicic 0:c0ecb8bf28eb 3019 OP_GET,
Marko Mikulicic 0:c0ecb8bf28eb 3020 /*
Marko Mikulicic 0:c0ecb8bf28eb 3021 * Takes 3 items from the stack: value, property name, object. Sets the given
Marko Mikulicic 0:c0ecb8bf28eb 3022 * property of a given object to a given value, pushes value back onto the
Marko Mikulicic 0:c0ecb8bf28eb 3023 *stack.
Marko Mikulicic 0:c0ecb8bf28eb 3024 *
Marko Mikulicic 0:c0ecb8bf28eb 3025 * `( a b c -- a[b]=c )`
Marko Mikulicic 0:c0ecb8bf28eb 3026 */
Marko Mikulicic 0:c0ecb8bf28eb 3027 OP_SET,
Marko Mikulicic 0:c0ecb8bf28eb 3028 /*
Marko Mikulicic 0:c0ecb8bf28eb 3029 * Takes 1 value from the stack and a varint argument -- index of the var name
Marko Mikulicic 0:c0ecb8bf28eb 3030 * in the literals table. Tries to find the variable in the current scope
Marko Mikulicic 0:c0ecb8bf28eb 3031 * chain and assign the value to it. If the varialble is not found -- creates
Marko Mikulicic 0:c0ecb8bf28eb 3032 * a new one in the global scope. Pushes the value back to the stack.
Marko Mikulicic 0:c0ecb8bf28eb 3033 *
Marko Mikulicic 0:c0ecb8bf28eb 3034 * `( a -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3035 */
Marko Mikulicic 0:c0ecb8bf28eb 3036 OP_SET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3037 /*
Marko Mikulicic 0:c0ecb8bf28eb 3038 * Takes a varint argument -- index of the var name in the literals table.
Marko Mikulicic 0:c0ecb8bf28eb 3039 * Looks up that variable in the scope chain and pushes its value onto the
Marko Mikulicic 0:c0ecb8bf28eb 3040 * stack.
Marko Mikulicic 0:c0ecb8bf28eb 3041 *
Marko Mikulicic 0:c0ecb8bf28eb 3042 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3043 */
Marko Mikulicic 0:c0ecb8bf28eb 3044 OP_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3045
Marko Mikulicic 0:c0ecb8bf28eb 3046 /*
Marko Mikulicic 0:c0ecb8bf28eb 3047 * Like OP_GET_VAR but returns undefined
Marko Mikulicic 0:c0ecb8bf28eb 3048 * instead of throwing reference error.
Marko Mikulicic 0:c0ecb8bf28eb 3049 *
Marko Mikulicic 0:c0ecb8bf28eb 3050 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3051 */
Marko Mikulicic 0:c0ecb8bf28eb 3052 OP_SAFE_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3053
Marko Mikulicic 0:c0ecb8bf28eb 3054 /*
Marko Mikulicic 0:c0ecb8bf28eb 3055 * ==== Jumps
Marko Mikulicic 0:c0ecb8bf28eb 3056 *
Marko Mikulicic 0:c0ecb8bf28eb 3057 * All jump instructions take one 4-byte argument: offset to jump to. Offset
Marko Mikulicic 0:c0ecb8bf28eb 3058 *is a
Marko Mikulicic 0:c0ecb8bf28eb 3059 * index of the byte in the instruction stream, starting with 0. No byte order
Marko Mikulicic 0:c0ecb8bf28eb 3060 * conversion is applied.
Marko Mikulicic 0:c0ecb8bf28eb 3061 *
Marko Mikulicic 0:c0ecb8bf28eb 3062 * TODO: specify byte order for the offset.
Marko Mikulicic 0:c0ecb8bf28eb 3063 */
Marko Mikulicic 0:c0ecb8bf28eb 3064
Marko Mikulicic 0:c0ecb8bf28eb 3065 /*
Marko Mikulicic 0:c0ecb8bf28eb 3066 * Unconditiona jump.
Marko Mikulicic 0:c0ecb8bf28eb 3067 */
Marko Mikulicic 0:c0ecb8bf28eb 3068 OP_JMP,
Marko Mikulicic 0:c0ecb8bf28eb 3069 /*
Marko Mikulicic 0:c0ecb8bf28eb 3070 * Takes one value from the stack and performs a jump if conversion of that
Marko Mikulicic 0:c0ecb8bf28eb 3071 * value to boolean results in `true`.
Marko Mikulicic 0:c0ecb8bf28eb 3072 *
Marko Mikulicic 0:c0ecb8bf28eb 3073 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3074 */
Marko Mikulicic 0:c0ecb8bf28eb 3075 OP_JMP_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 3076 /*
Marko Mikulicic 0:c0ecb8bf28eb 3077 * Takes one value from the stack and performs a jump if conversion of that
Marko Mikulicic 0:c0ecb8bf28eb 3078 * value to boolean results in `false`.
Marko Mikulicic 0:c0ecb8bf28eb 3079 *
Marko Mikulicic 0:c0ecb8bf28eb 3080 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3081 */
Marko Mikulicic 0:c0ecb8bf28eb 3082 OP_JMP_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 3083 /*
Marko Mikulicic 0:c0ecb8bf28eb 3084 * Like OP_JMP_TRUE but if the branch
Marko Mikulicic 0:c0ecb8bf28eb 3085 * is taken it also drops another stack element:
Marko Mikulicic 0:c0ecb8bf28eb 3086 *
Marko Mikulicic 0:c0ecb8bf28eb 3087 * if `b` is true: `( a b -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3088 * if `b` is false: `( a b -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3089 */
Marko Mikulicic 0:c0ecb8bf28eb 3090 OP_JMP_TRUE_DROP,
Marko Mikulicic 0:c0ecb8bf28eb 3091
Marko Mikulicic 0:c0ecb8bf28eb 3092 /*
Marko Mikulicic 0:c0ecb8bf28eb 3093 * Conditional jump on the v7->is_continuing flag.
Marko Mikulicic 0:c0ecb8bf28eb 3094 * Clears the flag once executed.
Marko Mikulicic 0:c0ecb8bf28eb 3095 *
Marko Mikulicic 0:c0ecb8bf28eb 3096 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3097 */
Marko Mikulicic 0:c0ecb8bf28eb 3098 OP_JMP_IF_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 3099
Marko Mikulicic 0:c0ecb8bf28eb 3100 /*
Marko Mikulicic 0:c0ecb8bf28eb 3101 * Constructs a new empty object and pushes it onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 3102 *
Marko Mikulicic 0:c0ecb8bf28eb 3103 * `( -- {} )`
Marko Mikulicic 0:c0ecb8bf28eb 3104 */
Marko Mikulicic 0:c0ecb8bf28eb 3105 OP_CREATE_OBJ,
Marko Mikulicic 0:c0ecb8bf28eb 3106 /*
Marko Mikulicic 0:c0ecb8bf28eb 3107 * Constructs a new empty array and pushes it onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 3108 *
Marko Mikulicic 0:c0ecb8bf28eb 3109 * `( -- [] )`
Marko Mikulicic 0:c0ecb8bf28eb 3110 */
Marko Mikulicic 0:c0ecb8bf28eb 3111 OP_CREATE_ARR,
Marko Mikulicic 0:c0ecb8bf28eb 3112
Marko Mikulicic 0:c0ecb8bf28eb 3113 /*
Marko Mikulicic 0:c0ecb8bf28eb 3114 * Allocates the iteration context (for `OP_NEXT_PROP`) from heap and pushes
Marko Mikulicic 0:c0ecb8bf28eb 3115 * a foreign pointer to it on stack. The allocated data is stored as "user
Marko Mikulicic 0:c0ecb8bf28eb 3116 * data" of the object, and it will be reclaimed automatically when the
Marko Mikulicic 0:c0ecb8bf28eb 3117 * object gets garbage-collected.
Marko Mikulicic 0:c0ecb8bf28eb 3118 *
Marko Mikulicic 0:c0ecb8bf28eb 3119 * `( -- ctx )`
Marko Mikulicic 0:c0ecb8bf28eb 3120 */
Marko Mikulicic 0:c0ecb8bf28eb 3121 OP_PUSH_PROP_ITER_CTX,
Marko Mikulicic 0:c0ecb8bf28eb 3122
Marko Mikulicic 0:c0ecb8bf28eb 3123 /*
Marko Mikulicic 0:c0ecb8bf28eb 3124 * Yields the next property name.
Marko Mikulicic 0:c0ecb8bf28eb 3125 * Used in the for..in construct.
Marko Mikulicic 0:c0ecb8bf28eb 3126 *
Marko Mikulicic 0:c0ecb8bf28eb 3127 * The first evaluation must receive `null` as handle.
Marko Mikulicic 0:c0ecb8bf28eb 3128 * Subsequent evaluations will either:
Marko Mikulicic 0:c0ecb8bf28eb 3129 *
Marko Mikulicic 0:c0ecb8bf28eb 3130 * a) produce a new handle, the key and true value:
Marko Mikulicic 0:c0ecb8bf28eb 3131 *
Marko Mikulicic 0:c0ecb8bf28eb 3132 * `( o h -- o h' key true)`
Marko Mikulicic 0:c0ecb8bf28eb 3133 *
Marko Mikulicic 0:c0ecb8bf28eb 3134 * b) produce a false value only, indicating no more properties:
Marko Mikulicic 0:c0ecb8bf28eb 3135 *
Marko Mikulicic 0:c0ecb8bf28eb 3136 * `( o h -- false)`
Marko Mikulicic 0:c0ecb8bf28eb 3137 */
Marko Mikulicic 0:c0ecb8bf28eb 3138 OP_NEXT_PROP,
Marko Mikulicic 0:c0ecb8bf28eb 3139
Marko Mikulicic 0:c0ecb8bf28eb 3140 /*
Marko Mikulicic 0:c0ecb8bf28eb 3141 * Copies the function object at TOS and assigns current scope
Marko Mikulicic 0:c0ecb8bf28eb 3142 * in func->scope.
Marko Mikulicic 0:c0ecb8bf28eb 3143 *
Marko Mikulicic 0:c0ecb8bf28eb 3144 * `( a -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3145 */
Marko Mikulicic 0:c0ecb8bf28eb 3146 OP_FUNC_LIT,
Marko Mikulicic 0:c0ecb8bf28eb 3147 /*
Marko Mikulicic 0:c0ecb8bf28eb 3148 * Takes the number of arguments as parameter.
Marko Mikulicic 0:c0ecb8bf28eb 3149 *
Marko Mikulicic 0:c0ecb8bf28eb 3150 * Pops N function arguments from stack, then pops function, then pops `this`.
Marko Mikulicic 0:c0ecb8bf28eb 3151 * Calls a function and populates TOS with the returned value.
Marko Mikulicic 0:c0ecb8bf28eb 3152 *
Marko Mikulicic 0:c0ecb8bf28eb 3153 * `( this f a0 a1 ... aN -- f(a0,a1,...) )`
Marko Mikulicic 0:c0ecb8bf28eb 3154 */
Marko Mikulicic 0:c0ecb8bf28eb 3155 OP_CALL,
Marko Mikulicic 0:c0ecb8bf28eb 3156 OP_NEW,
Marko Mikulicic 0:c0ecb8bf28eb 3157 /*
Marko Mikulicic 0:c0ecb8bf28eb 3158 * Checks that TOS is a callable and if not saves an exception
Marko Mikulicic 0:c0ecb8bf28eb 3159 * that will will be thrown by CALL after all arguments have been evaluated.
Marko Mikulicic 0:c0ecb8bf28eb 3160 */
Marko Mikulicic 0:c0ecb8bf28eb 3161 OP_CHECK_CALL,
Marko Mikulicic 0:c0ecb8bf28eb 3162 /*
Marko Mikulicic 0:c0ecb8bf28eb 3163 * Returns the current function.
Marko Mikulicic 0:c0ecb8bf28eb 3164 *
Marko Mikulicic 0:c0ecb8bf28eb 3165 * It has no stack side effects. The function upon return will leave the
Marko Mikulicic 0:c0ecb8bf28eb 3166 * return value on the stack. The return value must be pushed on the stack
Marko Mikulicic 0:c0ecb8bf28eb 3167 * prior to invoking a RET.
Marko Mikulicic 0:c0ecb8bf28eb 3168 *
Marko Mikulicic 0:c0ecb8bf28eb 3169 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3170 */
Marko Mikulicic 0:c0ecb8bf28eb 3171 OP_RET,
Marko Mikulicic 0:c0ecb8bf28eb 3172
Marko Mikulicic 0:c0ecb8bf28eb 3173 /*
Marko Mikulicic 0:c0ecb8bf28eb 3174 * Deletes the property of given name `p` from the given object `o`. Returns
Marko Mikulicic 0:c0ecb8bf28eb 3175 * boolean value `a`.
Marko Mikulicic 0:c0ecb8bf28eb 3176 *
Marko Mikulicic 0:c0ecb8bf28eb 3177 * `( o p -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3178 */
Marko Mikulicic 0:c0ecb8bf28eb 3179 OP_DELETE,
Marko Mikulicic 0:c0ecb8bf28eb 3180
Marko Mikulicic 0:c0ecb8bf28eb 3181 /*
Marko Mikulicic 0:c0ecb8bf28eb 3182 * Like `OP_DELETE`, but uses the current scope as an object to delete
Marko Mikulicic 0:c0ecb8bf28eb 3183 * a property from.
Marko Mikulicic 0:c0ecb8bf28eb 3184 *
Marko Mikulicic 0:c0ecb8bf28eb 3185 * `( p -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3186 */
Marko Mikulicic 0:c0ecb8bf28eb 3187 OP_DELETE_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3188
Marko Mikulicic 0:c0ecb8bf28eb 3189 /*
Marko Mikulicic 0:c0ecb8bf28eb 3190 * Pushes a value (bcode offset of `catch` block) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3191 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3192 *
Marko Mikulicic 0:c0ecb8bf28eb 3193 * Used in the beginning of the `try` block.
Marko Mikulicic 0:c0ecb8bf28eb 3194 *
Marko Mikulicic 0:c0ecb8bf28eb 3195 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3196 */
Marko Mikulicic 0:c0ecb8bf28eb 3197 OP_TRY_PUSH_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 3198
Marko Mikulicic 0:c0ecb8bf28eb 3199 /*
Marko Mikulicic 0:c0ecb8bf28eb 3200 * Pushes a value (bcode offset of `finally` block) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3201 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3202 *
Marko Mikulicic 0:c0ecb8bf28eb 3203 * Used in the beginning of the `try` block.
Marko Mikulicic 0:c0ecb8bf28eb 3204 *
Marko Mikulicic 0:c0ecb8bf28eb 3205 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3206 *
Marko Mikulicic 0:c0ecb8bf28eb 3207 * TODO: implement me
Marko Mikulicic 0:c0ecb8bf28eb 3208 */
Marko Mikulicic 0:c0ecb8bf28eb 3209 OP_TRY_PUSH_FINALLY,
Marko Mikulicic 0:c0ecb8bf28eb 3210
Marko Mikulicic 0:c0ecb8bf28eb 3211 /*
Marko Mikulicic 0:c0ecb8bf28eb 3212 * Pushes a value (bcode offset of a label) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3213 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3214 *
Marko Mikulicic 0:c0ecb8bf28eb 3215 * Used at the beginning of loops that contain break or continue.
Marko Mikulicic 0:c0ecb8bf28eb 3216 * Possible optimisation: don't emit if we can ensure that no break or
Marko Mikulicic 0:c0ecb8bf28eb 3217 * continue statement is used.
Marko Mikulicic 0:c0ecb8bf28eb 3218 *
Marko Mikulicic 0:c0ecb8bf28eb 3219 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3220 */
Marko Mikulicic 0:c0ecb8bf28eb 3221 OP_TRY_PUSH_LOOP,
Marko Mikulicic 0:c0ecb8bf28eb 3222
Marko Mikulicic 0:c0ecb8bf28eb 3223 /*
Marko Mikulicic 0:c0ecb8bf28eb 3224 * Pushes a value (bcode offset of a label) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3225 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3226 *
Marko Mikulicic 0:c0ecb8bf28eb 3227 * Used at the beginning of switch statements.
Marko Mikulicic 0:c0ecb8bf28eb 3228 *
Marko Mikulicic 0:c0ecb8bf28eb 3229 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3230 */
Marko Mikulicic 0:c0ecb8bf28eb 3231 OP_TRY_PUSH_SWITCH,
Marko Mikulicic 0:c0ecb8bf28eb 3232
Marko Mikulicic 0:c0ecb8bf28eb 3233 /*
Marko Mikulicic 0:c0ecb8bf28eb 3234 * Pops a value (bcode offset of `finally` or `catch` block) from "try
Marko Mikulicic 0:c0ecb8bf28eb 3235 * stack", and discards it
Marko Mikulicic 0:c0ecb8bf28eb 3236 *
Marko Mikulicic 0:c0ecb8bf28eb 3237 * Used in the end of the `try` block, as well as in the beginning of the
Marko Mikulicic 0:c0ecb8bf28eb 3238 * `catch` and `finally` blocks
Marko Mikulicic 0:c0ecb8bf28eb 3239 *
Marko Mikulicic 0:c0ecb8bf28eb 3240 * `( T: a -- T: )`
Marko Mikulicic 0:c0ecb8bf28eb 3241 */
Marko Mikulicic 0:c0ecb8bf28eb 3242 OP_TRY_POP,
Marko Mikulicic 0:c0ecb8bf28eb 3243
Marko Mikulicic 0:c0ecb8bf28eb 3244 /*
Marko Mikulicic 0:c0ecb8bf28eb 3245 * Used in the end of the `finally` block:
Marko Mikulicic 0:c0ecb8bf28eb 3246 *
Marko Mikulicic 0:c0ecb8bf28eb 3247 * - if some value is currently being thrown, keep throwing it.
Marko Mikulicic 0:c0ecb8bf28eb 3248 * If eventually we encounter `catch` block, the thrown value gets
Marko Mikulicic 0:c0ecb8bf28eb 3249 * populated on TOS:
Marko Mikulicic 0:c0ecb8bf28eb 3250 *
Marko Mikulicic 0:c0ecb8bf28eb 3251 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3252 *
Marko Mikulicic 0:c0ecb8bf28eb 3253 * - if there is some pending value to return, keep returning it.
Marko Mikulicic 0:c0ecb8bf28eb 3254 * If we encounter no further `finally` blocks, then the returned value
Marko Mikulicic 0:c0ecb8bf28eb 3255 * gets populated on TOS:
Marko Mikulicic 0:c0ecb8bf28eb 3256 *
Marko Mikulicic 0:c0ecb8bf28eb 3257 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3258 *
Marko Mikulicic 0:c0ecb8bf28eb 3259 * And return is performed.
Marko Mikulicic 0:c0ecb8bf28eb 3260 *
Marko Mikulicic 0:c0ecb8bf28eb 3261 * - otherwise, do nothing
Marko Mikulicic 0:c0ecb8bf28eb 3262 */
Marko Mikulicic 0:c0ecb8bf28eb 3263 OP_AFTER_FINALLY,
Marko Mikulicic 0:c0ecb8bf28eb 3264
Marko Mikulicic 0:c0ecb8bf28eb 3265 /*
Marko Mikulicic 0:c0ecb8bf28eb 3266 * Throw value from TOS. First of all, it pops the value and saves it into
Marko Mikulicic 0:c0ecb8bf28eb 3267 * `v7->vals.thrown_error`:
Marko Mikulicic 0:c0ecb8bf28eb 3268 *
Marko Mikulicic 0:c0ecb8bf28eb 3269 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3270 *
Marko Mikulicic 0:c0ecb8bf28eb 3271 * Then unwinds stack looking for the first `catch` or `finally` blocks.
Marko Mikulicic 0:c0ecb8bf28eb 3272 *
Marko Mikulicic 0:c0ecb8bf28eb 3273 * - if `finally` is found, thrown value is kept into `v7->vals.thrown_error`.
Marko Mikulicic 0:c0ecb8bf28eb 3274 * - if `catch` is found, thrown value is pushed back to the stack:
Marko Mikulicic 0:c0ecb8bf28eb 3275 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3276 * - otherwise, thrown value is kept into `v7->vals.thrown_error`
Marko Mikulicic 0:c0ecb8bf28eb 3277 */
Marko Mikulicic 0:c0ecb8bf28eb 3278 OP_THROW,
Marko Mikulicic 0:c0ecb8bf28eb 3279
Marko Mikulicic 0:c0ecb8bf28eb 3280 /*
Marko Mikulicic 0:c0ecb8bf28eb 3281 * Unwind to next break entry in the try stack, evaluating
Marko Mikulicic 0:c0ecb8bf28eb 3282 * all finally blocks on its way up.
Marko Mikulicic 0:c0ecb8bf28eb 3283 *
Marko Mikulicic 0:c0ecb8bf28eb 3284 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3285 */
Marko Mikulicic 0:c0ecb8bf28eb 3286 OP_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 3287
Marko Mikulicic 0:c0ecb8bf28eb 3288 /*
Marko Mikulicic 0:c0ecb8bf28eb 3289 * Like OP_BREAK, but sets the v7->is_continuing flag
Marko Mikulicic 0:c0ecb8bf28eb 3290 * which will cause OP_JMP_IF_CONTINUE to restart the loop.
Marko Mikulicic 0:c0ecb8bf28eb 3291 *
Marko Mikulicic 0:c0ecb8bf28eb 3292 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3293 */
Marko Mikulicic 0:c0ecb8bf28eb 3294 OP_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 3295
Marko Mikulicic 0:c0ecb8bf28eb 3296 /*
Marko Mikulicic 0:c0ecb8bf28eb 3297 * Used when we enter the `catch` block. Takes a varint argument -- index of
Marko Mikulicic 0:c0ecb8bf28eb 3298 * the exception variable name in the literals table.
Marko Mikulicic 0:c0ecb8bf28eb 3299 *
Marko Mikulicic 0:c0ecb8bf28eb 3300 * Pops the exception value from the stack, creates a private frame,
Marko Mikulicic 0:c0ecb8bf28eb 3301 * sets exception property on it with the given name. pushes this
Marko Mikulicic 0:c0ecb8bf28eb 3302 * private frame to call stack.
Marko Mikulicic 0:c0ecb8bf28eb 3303 *
Marko Mikulicic 0:c0ecb8bf28eb 3304 * `( e -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3305 */
Marko Mikulicic 0:c0ecb8bf28eb 3306 OP_ENTER_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 3307
Marko Mikulicic 0:c0ecb8bf28eb 3308 /*
Marko Mikulicic 0:c0ecb8bf28eb 3309 * Ued when we exit from the `catch` block. Merely pops the private frame
Marko Mikulicic 0:c0ecb8bf28eb 3310 * from the call stack.
Marko Mikulicic 0:c0ecb8bf28eb 3311 *
Marko Mikulicic 0:c0ecb8bf28eb 3312 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3313 */
Marko Mikulicic 0:c0ecb8bf28eb 3314 OP_EXIT_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 3315
Marko Mikulicic 0:c0ecb8bf28eb 3316 OP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 3317 };
Marko Mikulicic 0:c0ecb8bf28eb 3318
Marko Mikulicic 0:c0ecb8bf28eb 3319 #define _OP_LINE_NO 0x80
Marko Mikulicic 0:c0ecb8bf28eb 3320
Marko Mikulicic 0:c0ecb8bf28eb 3321 #endif /* CS_V7_SRC_OPCODES_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 3322 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 3323 #line 1 "v7/src/core.h"
Marko Mikulicic 0:c0ecb8bf28eb 3324 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3325 /*
Marko Mikulicic 0:c0ecb8bf28eb 3326 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 3327 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 3328 */
Marko Mikulicic 0:c0ecb8bf28eb 3329
Marko Mikulicic 0:c0ecb8bf28eb 3330 #ifndef CS_V7_SRC_CORE_H_
Marko Mikulicic 0:c0ecb8bf28eb 3331 #define CS_V7_SRC_CORE_H_
Marko Mikulicic 0:c0ecb8bf28eb 3332
Marko Mikulicic 0:c0ecb8bf28eb 3333 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3334
Marko Mikulicic 0:c0ecb8bf28eb 3335 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3336 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3337 /* Amalgamated: #include "v7/src/mm.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3338 /* Amalgamated: #include "v7/src/parser.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3339 /* Amalgamated: #include "v7/src/object_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3340 /* Amalgamated: #include "v7/src/tokenizer.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3341 /* Amalgamated: #include "v7/src/opcodes.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3342
Marko Mikulicic 0:c0ecb8bf28eb 3343 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 3344 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 3345 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 3346
Marko Mikulicic 0:c0ecb8bf28eb 3347 typedef uint64_t val_t;
Marko Mikulicic 0:c0ecb8bf28eb 3348
Marko Mikulicic 0:c0ecb8bf28eb 3349 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 3350
Marko Mikulicic 0:c0ecb8bf28eb 3351 typedef unsigned short entity_id_t;
Marko Mikulicic 0:c0ecb8bf28eb 3352 typedef unsigned char entity_id_part_t;
Marko Mikulicic 0:c0ecb8bf28eb 3353
Marko Mikulicic 0:c0ecb8bf28eb 3354 /*
Marko Mikulicic 0:c0ecb8bf28eb 3355 * Magic numbers that are stored in various objects in order to identify their
Marko Mikulicic 0:c0ecb8bf28eb 3356 * type in runtime
Marko Mikulicic 0:c0ecb8bf28eb 3357 */
Marko Mikulicic 0:c0ecb8bf28eb 3358 #define V7_ENTITY_ID_PROP 0xe9a1
Marko Mikulicic 0:c0ecb8bf28eb 3359 #define V7_ENTITY_ID_PART_OBJ 0x57
Marko Mikulicic 0:c0ecb8bf28eb 3360 #define V7_ENTITY_ID_PART_GEN_OBJ 0x31
Marko Mikulicic 0:c0ecb8bf28eb 3361 #define V7_ENTITY_ID_PART_JS_FUNC 0x0d
Marko Mikulicic 0:c0ecb8bf28eb 3362
Marko Mikulicic 0:c0ecb8bf28eb 3363 #define V7_ENTITY_ID_NONE 0xa5a5
Marko Mikulicic 0:c0ecb8bf28eb 3364 #define V7_ENTITY_ID_PART_NONE 0xa5
Marko Mikulicic 0:c0ecb8bf28eb 3365
Marko Mikulicic 0:c0ecb8bf28eb 3366 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3367
Marko Mikulicic 0:c0ecb8bf28eb 3368 /*
Marko Mikulicic 0:c0ecb8bf28eb 3369 * Double-precision floating-point number, IEEE 754
Marko Mikulicic 0:c0ecb8bf28eb 3370 *
Marko Mikulicic 0:c0ecb8bf28eb 3371 * 64 bit (8 bytes) in total
Marko Mikulicic 0:c0ecb8bf28eb 3372 * 1 bit sign
Marko Mikulicic 0:c0ecb8bf28eb 3373 * 11 bits exponent
Marko Mikulicic 0:c0ecb8bf28eb 3374 * 52 bits mantissa
Marko Mikulicic 0:c0ecb8bf28eb 3375 * 7 6 5 4 3 2 1 0
Marko Mikulicic 0:c0ecb8bf28eb 3376 * seeeeeee|eeeemmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm
Marko Mikulicic 0:c0ecb8bf28eb 3377 *
Marko Mikulicic 0:c0ecb8bf28eb 3378 * If an exponent is all-1 and mantissa is all-0, then it is an INFINITY:
Marko Mikulicic 0:c0ecb8bf28eb 3379 * 11111111|11110000|00000000|00000000|00000000|00000000|00000000|00000000
Marko Mikulicic 0:c0ecb8bf28eb 3380 *
Marko Mikulicic 0:c0ecb8bf28eb 3381 * If an exponent is all-1 and mantissa's MSB is 1, it is a quiet NaN:
Marko Mikulicic 0:c0ecb8bf28eb 3382 * 11111111|11111000|00000000|00000000|00000000|00000000|00000000|00000000
Marko Mikulicic 0:c0ecb8bf28eb 3383 *
Marko Mikulicic 0:c0ecb8bf28eb 3384 * V7 NaN-packing:
Marko Mikulicic 0:c0ecb8bf28eb 3385 * sign and exponent is 0xfff
Marko Mikulicic 0:c0ecb8bf28eb 3386 * 4 bits specify type (tag), must be non-zero
Marko Mikulicic 0:c0ecb8bf28eb 3387 * 48 bits specify value
Marko Mikulicic 0:c0ecb8bf28eb 3388 *
Marko Mikulicic 0:c0ecb8bf28eb 3389 * 11111111|1111tttt|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv
Marko Mikulicic 0:c0ecb8bf28eb 3390 * NaN marker |type| 48-bit placeholder for values: pointers, strings
Marko Mikulicic 0:c0ecb8bf28eb 3391 *
Marko Mikulicic 0:c0ecb8bf28eb 3392 * On 64-bit platforms, pointers are really 48 bit only, so they can fit,
Marko Mikulicic 0:c0ecb8bf28eb 3393 * provided they are sign extended
Marko Mikulicic 0:c0ecb8bf28eb 3394 */
Marko Mikulicic 0:c0ecb8bf28eb 3395
Marko Mikulicic 0:c0ecb8bf28eb 3396 /*
Marko Mikulicic 0:c0ecb8bf28eb 3397 * A tag is made of the sign bit and the 4 lower order bits of byte 6.
Marko Mikulicic 0:c0ecb8bf28eb 3398 * So in total we have 32 possible tags.
Marko Mikulicic 0:c0ecb8bf28eb 3399 *
Marko Mikulicic 0:c0ecb8bf28eb 3400 * Tag (1,0) however cannot hold a zero payload otherwise it's interpreted as an
Marko Mikulicic 0:c0ecb8bf28eb 3401 * INFINITY; for simplicity we're just not going to use that combination.
Marko Mikulicic 0:c0ecb8bf28eb 3402 */
Marko Mikulicic 0:c0ecb8bf28eb 3403 #define MAKE_TAG(s, t) \
Marko Mikulicic 0:c0ecb8bf28eb 3404 ((uint64_t)(s) << 63 | (uint64_t) 0x7ff0 << 48 | (uint64_t)(t) << 48)
Marko Mikulicic 0:c0ecb8bf28eb 3405
Marko Mikulicic 0:c0ecb8bf28eb 3406 #define V7_TAG_OBJECT MAKE_TAG(1, 0xF)
Marko Mikulicic 0:c0ecb8bf28eb 3407 #define V7_TAG_FOREIGN MAKE_TAG(1, 0xE)
Marko Mikulicic 0:c0ecb8bf28eb 3408 #define V7_TAG_UNDEFINED MAKE_TAG(1, 0xD)
Marko Mikulicic 0:c0ecb8bf28eb 3409 #define V7_TAG_BOOLEAN MAKE_TAG(1, 0xC)
Marko Mikulicic 0:c0ecb8bf28eb 3410 #define V7_TAG_NAN MAKE_TAG(1, 0xB)
Marko Mikulicic 0:c0ecb8bf28eb 3411 #define V7_TAG_STRING_I MAKE_TAG(1, 0xA) /* Inlined string len < 5 */
Marko Mikulicic 0:c0ecb8bf28eb 3412 #define V7_TAG_STRING_5 MAKE_TAG(1, 0x9) /* Inlined string len 5 */
Marko Mikulicic 0:c0ecb8bf28eb 3413 #define V7_TAG_STRING_O MAKE_TAG(1, 0x8) /* Owned string */
Marko Mikulicic 0:c0ecb8bf28eb 3414 #define V7_TAG_STRING_F MAKE_TAG(1, 0x7) /* Foreign string */
Marko Mikulicic 0:c0ecb8bf28eb 3415 #define V7_TAG_STRING_C MAKE_TAG(1, 0x6) /* String chunk */
Marko Mikulicic 0:c0ecb8bf28eb 3416 #define V7_TAG_FUNCTION MAKE_TAG(1, 0x5) /* JavaScript function */
Marko Mikulicic 0:c0ecb8bf28eb 3417 #define V7_TAG_CFUNCTION MAKE_TAG(1, 0x4) /* C function */
Marko Mikulicic 0:c0ecb8bf28eb 3418 #define V7_TAG_STRING_D MAKE_TAG(1, 0x3) /* Dictionary string */
Marko Mikulicic 0:c0ecb8bf28eb 3419 #define V7_TAG_REGEXP MAKE_TAG(1, 0x2) /* Regex */
Marko Mikulicic 0:c0ecb8bf28eb 3420 #define V7_TAG_NOVALUE MAKE_TAG(1, 0x1) /* Sentinel for no value */
Marko Mikulicic 0:c0ecb8bf28eb 3421 #define V7_TAG_MASK MAKE_TAG(1, 0xF)
Marko Mikulicic 0:c0ecb8bf28eb 3422
Marko Mikulicic 0:c0ecb8bf28eb 3423 #define _V7_NULL V7_TAG_FOREIGN
Marko Mikulicic 0:c0ecb8bf28eb 3424 #define _V7_UNDEFINED V7_TAG_UNDEFINED
Marko Mikulicic 0:c0ecb8bf28eb 3425
Marko Mikulicic 0:c0ecb8bf28eb 3426 V7_STATIC_ASSERT(_V7_NULL == V7_NULL, public_V7_NULL_is_wrong);
Marko Mikulicic 0:c0ecb8bf28eb 3427 V7_STATIC_ASSERT(_V7_UNDEFINED == V7_UNDEFINED, public_V7_UNDEFINED_is_wrong);
Marko Mikulicic 0:c0ecb8bf28eb 3428
Marko Mikulicic 0:c0ecb8bf28eb 3429 /*
Marko Mikulicic 0:c0ecb8bf28eb 3430 * Object attributes bitmask
Marko Mikulicic 0:c0ecb8bf28eb 3431 */
Marko Mikulicic 0:c0ecb8bf28eb 3432 typedef unsigned char v7_obj_attr_t;
Marko Mikulicic 0:c0ecb8bf28eb 3433 #define V7_OBJ_NOT_EXTENSIBLE (1 << 0) /* TODO(lsm): store this in LSB */
Marko Mikulicic 0:c0ecb8bf28eb 3434 #define V7_OBJ_DENSE_ARRAY (1 << 1) /* TODO(mkm): store in some tag */
Marko Mikulicic 0:c0ecb8bf28eb 3435 #define V7_OBJ_FUNCTION (1 << 2) /* function object */
Marko Mikulicic 0:c0ecb8bf28eb 3436 #define V7_OBJ_OFF_HEAP (1 << 3) /* object not managed by V7 HEAP */
Marko Mikulicic 0:c0ecb8bf28eb 3437 #define V7_OBJ_HAS_DESTRUCTOR (1 << 4) /* has user data */
Marko Mikulicic 0:c0ecb8bf28eb 3438 #define V7_OBJ_PROXY (1 << 5) /* it's a Proxy object */
Marko Mikulicic 0:c0ecb8bf28eb 3439
Marko Mikulicic 0:c0ecb8bf28eb 3440 /*
Marko Mikulicic 0:c0ecb8bf28eb 3441 * JavaScript value is either a primitive, or an object.
Marko Mikulicic 0:c0ecb8bf28eb 3442 * There are 5 primitive types: Undefined, Null, Boolean, Number, String.
Marko Mikulicic 0:c0ecb8bf28eb 3443 * Non-primitive type is an Object type. There are several classes of Objects,
Marko Mikulicic 0:c0ecb8bf28eb 3444 * see description of `struct v7_generic_object` below for more details.
Marko Mikulicic 0:c0ecb8bf28eb 3445 * This enumeration combines types and object classes in one enumeration.
Marko Mikulicic 0:c0ecb8bf28eb 3446 * NOTE(lsm): compile with `-fshort-enums` to reduce sizeof(enum v7_type) to 1.
Marko Mikulicic 0:c0ecb8bf28eb 3447 */
Marko Mikulicic 0:c0ecb8bf28eb 3448 enum v7_type {
Marko Mikulicic 0:c0ecb8bf28eb 3449 /* Primitive types */
Marko Mikulicic 0:c0ecb8bf28eb 3450 V7_TYPE_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 3451 V7_TYPE_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 3452 V7_TYPE_BOOLEAN,
Marko Mikulicic 0:c0ecb8bf28eb 3453 V7_TYPE_NUMBER,
Marko Mikulicic 0:c0ecb8bf28eb 3454 V7_TYPE_STRING,
Marko Mikulicic 0:c0ecb8bf28eb 3455 V7_TYPE_FOREIGN,
Marko Mikulicic 0:c0ecb8bf28eb 3456 V7_TYPE_CFUNCTION,
Marko Mikulicic 0:c0ecb8bf28eb 3457
Marko Mikulicic 0:c0ecb8bf28eb 3458 /* Different classes of Object type */
Marko Mikulicic 0:c0ecb8bf28eb 3459 V7_TYPE_GENERIC_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3460 V7_TYPE_BOOLEAN_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3461 V7_TYPE_STRING_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3462 V7_TYPE_NUMBER_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3463 V7_TYPE_FUNCTION_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3464 V7_TYPE_CFUNCTION_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3465 V7_TYPE_REGEXP_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3466 V7_TYPE_ARRAY_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3467 V7_TYPE_DATE_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3468 V7_TYPE_ERROR_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3469 V7_TYPE_MAX_OBJECT_TYPE,
Marko Mikulicic 0:c0ecb8bf28eb 3470 V7_NUM_TYPES
Marko Mikulicic 0:c0ecb8bf28eb 3471 };
Marko Mikulicic 0:c0ecb8bf28eb 3472
Marko Mikulicic 0:c0ecb8bf28eb 3473 /*
Marko Mikulicic 0:c0ecb8bf28eb 3474 * Call frame type mask: we have a "class hierarchy" of the call frames, see
Marko Mikulicic 0:c0ecb8bf28eb 3475 * `struct v7_call_frame_base`, and the `type_mask` field represents the exact
Marko Mikulicic 0:c0ecb8bf28eb 3476 * frame type.
Marko Mikulicic 0:c0ecb8bf28eb 3477 *
Marko Mikulicic 0:c0ecb8bf28eb 3478 * Possible values are:
Marko Mikulicic 0:c0ecb8bf28eb 3479 *
Marko Mikulicic 0:c0ecb8bf28eb 3480 * - `V7_CALL_FRAME_MASK_PRIVATE | V7_CALL_FRAME_MASK_BCODE`: the most popular
Marko Mikulicic 0:c0ecb8bf28eb 3481 * frame type: call frame for bcode execution, either top-level code or JS
Marko Mikulicic 0:c0ecb8bf28eb 3482 * function.
Marko Mikulicic 0:c0ecb8bf28eb 3483 * - `V7_CALL_FRAME_MASK_PRIVATE`: used for `catch` clauses only: the variables
Marko Mikulicic 0:c0ecb8bf28eb 3484 * we create in `catch` clause should not be visible from the outside of the
Marko Mikulicic 0:c0ecb8bf28eb 3485 * clause, so we have to create a separate scope object for it.
Marko Mikulicic 0:c0ecb8bf28eb 3486 * - `V7_CALL_FRAME_MASK_CFUNC`: call frame for C function.
Marko Mikulicic 0:c0ecb8bf28eb 3487 */
Marko Mikulicic 0:c0ecb8bf28eb 3488 typedef uint8_t v7_call_frame_mask_t;
Marko Mikulicic 0:c0ecb8bf28eb 3489 #define V7_CALL_FRAME_MASK_BCODE (1 << 0)
Marko Mikulicic 0:c0ecb8bf28eb 3490 #define V7_CALL_FRAME_MASK_PRIVATE (1 << 1)
Marko Mikulicic 0:c0ecb8bf28eb 3491 #define V7_CALL_FRAME_MASK_CFUNC (1 << 2)
Marko Mikulicic 0:c0ecb8bf28eb 3492
Marko Mikulicic 0:c0ecb8bf28eb 3493 /*
Marko Mikulicic 0:c0ecb8bf28eb 3494 * Base of the call frame; includes the pointer to the previous frame,
Marko Mikulicic 0:c0ecb8bf28eb 3495 * and the frame type.
Marko Mikulicic 0:c0ecb8bf28eb 3496 *
Marko Mikulicic 0:c0ecb8bf28eb 3497 * In order to save memory, it also contains some bitfields which actually
Marko Mikulicic 0:c0ecb8bf28eb 3498 * belong to some "sub-structures".
Marko Mikulicic 0:c0ecb8bf28eb 3499 *
Marko Mikulicic 0:c0ecb8bf28eb 3500 * The hierarchy is as follows:
Marko Mikulicic 0:c0ecb8bf28eb 3501 *
Marko Mikulicic 0:c0ecb8bf28eb 3502 * - v7_call_frame_base
Marko Mikulicic 0:c0ecb8bf28eb 3503 * - v7_call_frame_private
Marko Mikulicic 0:c0ecb8bf28eb 3504 * - v7_call_frame_bcode
Marko Mikulicic 0:c0ecb8bf28eb 3505 * - v7_call_frame_cfunc
Marko Mikulicic 0:c0ecb8bf28eb 3506 */
Marko Mikulicic 0:c0ecb8bf28eb 3507 struct v7_call_frame_base {
Marko Mikulicic 0:c0ecb8bf28eb 3508 struct v7_call_frame_base *prev;
Marko Mikulicic 0:c0ecb8bf28eb 3509
Marko Mikulicic 0:c0ecb8bf28eb 3510 /* See comment for `v7_call_frame_mask_t` */
Marko Mikulicic 0:c0ecb8bf28eb 3511 v7_call_frame_mask_t type_mask : 3;
Marko Mikulicic 0:c0ecb8bf28eb 3512
Marko Mikulicic 0:c0ecb8bf28eb 3513 /* Belongs to `struct v7_call_frame_private` */
Marko Mikulicic 0:c0ecb8bf28eb 3514 unsigned int line_no : 16;
Marko Mikulicic 0:c0ecb8bf28eb 3515
Marko Mikulicic 0:c0ecb8bf28eb 3516 /* Belongs to `struct v7_call_frame_bcode` */
Marko Mikulicic 0:c0ecb8bf28eb 3517 unsigned is_constructor : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3518
Marko Mikulicic 0:c0ecb8bf28eb 3519 /* Belongs to `struct v7_call_frame_bcode` */
Marko Mikulicic 0:c0ecb8bf28eb 3520 unsigned int is_thrown : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3521 };
Marko Mikulicic 0:c0ecb8bf28eb 3522
Marko Mikulicic 0:c0ecb8bf28eb 3523 /*
Marko Mikulicic 0:c0ecb8bf28eb 3524 * "private" call frame, used in `catch` blocks, merely for using a separate
Marko Mikulicic 0:c0ecb8bf28eb 3525 * scope object there. It is also a "base class" for the bcode call frame,
Marko Mikulicic 0:c0ecb8bf28eb 3526 * see `struct v7_call_frame_bcode`.
Marko Mikulicic 0:c0ecb8bf28eb 3527 *
Marko Mikulicic 0:c0ecb8bf28eb 3528 * TODO(dfrank): probably implement it differently, so that we can get rid of
Marko Mikulicic 0:c0ecb8bf28eb 3529 * the separate "private" frames whatsoever (and just include it into struct
Marko Mikulicic 0:c0ecb8bf28eb 3530 * v7_call_frame_bcode )
Marko Mikulicic 0:c0ecb8bf28eb 3531 */
Marko Mikulicic 0:c0ecb8bf28eb 3532 struct v7_call_frame_private {
Marko Mikulicic 0:c0ecb8bf28eb 3533 struct v7_call_frame_base base;
Marko Mikulicic 0:c0ecb8bf28eb 3534 size_t stack_size;
Marko Mikulicic 0:c0ecb8bf28eb 3535 struct {
Marko Mikulicic 0:c0ecb8bf28eb 3536 /*
Marko Mikulicic 0:c0ecb8bf28eb 3537 * Current execution scope. Initially, it is equal to the `global_object`;
Marko Mikulicic 0:c0ecb8bf28eb 3538 * and at each function call, it is augmented by the new scope object, which
Marko Mikulicic 0:c0ecb8bf28eb 3539 * has the previous value as a prototype.
Marko Mikulicic 0:c0ecb8bf28eb 3540 */
Marko Mikulicic 0:c0ecb8bf28eb 3541 val_t scope;
Marko Mikulicic 0:c0ecb8bf28eb 3542
Marko Mikulicic 0:c0ecb8bf28eb 3543 val_t try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 3544 } vals;
Marko Mikulicic 0:c0ecb8bf28eb 3545 };
Marko Mikulicic 0:c0ecb8bf28eb 3546
Marko Mikulicic 0:c0ecb8bf28eb 3547 /*
Marko Mikulicic 0:c0ecb8bf28eb 3548 * "bcode" call frame, augments "private" frame with `bcode` and the position
Marko Mikulicic 0:c0ecb8bf28eb 3549 * in it, and `this` object. It is the primary frame type, used when executing
Marko Mikulicic 0:c0ecb8bf28eb 3550 * a bcode script or calling a function.
Marko Mikulicic 0:c0ecb8bf28eb 3551 */
Marko Mikulicic 0:c0ecb8bf28eb 3552 struct v7_call_frame_bcode {
Marko Mikulicic 0:c0ecb8bf28eb 3553 struct v7_call_frame_private base;
Marko Mikulicic 0:c0ecb8bf28eb 3554 struct {
Marko Mikulicic 0:c0ecb8bf28eb 3555 val_t this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 3556 val_t thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 3557 } vals;
Marko Mikulicic 0:c0ecb8bf28eb 3558 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 3559 char *bcode_ops;
Marko Mikulicic 0:c0ecb8bf28eb 3560 };
Marko Mikulicic 0:c0ecb8bf28eb 3561
Marko Mikulicic 0:c0ecb8bf28eb 3562 /*
Marko Mikulicic 0:c0ecb8bf28eb 3563 * "cfunc" call frame, used when calling cfunctions.
Marko Mikulicic 0:c0ecb8bf28eb 3564 */
Marko Mikulicic 0:c0ecb8bf28eb 3565 struct v7_call_frame_cfunc {
Marko Mikulicic 0:c0ecb8bf28eb 3566 struct v7_call_frame_base base;
Marko Mikulicic 0:c0ecb8bf28eb 3567
Marko Mikulicic 0:c0ecb8bf28eb 3568 struct {
Marko Mikulicic 0:c0ecb8bf28eb 3569 val_t this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 3570 } vals;
Marko Mikulicic 0:c0ecb8bf28eb 3571
Marko Mikulicic 0:c0ecb8bf28eb 3572 v7_cfunction_t *cfunc;
Marko Mikulicic 0:c0ecb8bf28eb 3573 };
Marko Mikulicic 0:c0ecb8bf28eb 3574
Marko Mikulicic 0:c0ecb8bf28eb 3575 /*
Marko Mikulicic 0:c0ecb8bf28eb 3576 * This structure groups together all val_t logical members
Marko Mikulicic 0:c0ecb8bf28eb 3577 * of struct v7 so that GC and freeze logic can easily access all
Marko Mikulicic 0:c0ecb8bf28eb 3578 * of them together. This structure must contain only val_t members.
Marko Mikulicic 0:c0ecb8bf28eb 3579 */
Marko Mikulicic 0:c0ecb8bf28eb 3580 struct v7_vals {
Marko Mikulicic 0:c0ecb8bf28eb 3581 val_t global_object;
Marko Mikulicic 0:c0ecb8bf28eb 3582
Marko Mikulicic 0:c0ecb8bf28eb 3583 val_t arguments; /* arguments of current call */
Marko Mikulicic 0:c0ecb8bf28eb 3584
Marko Mikulicic 0:c0ecb8bf28eb 3585 val_t object_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3586 val_t array_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3587 val_t boolean_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3588 val_t error_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3589 val_t string_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3590 val_t regexp_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3591 val_t number_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3592 val_t date_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3593 val_t function_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3594 val_t proxy_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3595
Marko Mikulicic 0:c0ecb8bf28eb 3596 /*
Marko Mikulicic 0:c0ecb8bf28eb 3597 * temporary register for `OP_STASH` and `OP_UNSTASH` instructions. Valid if
Marko Mikulicic 0:c0ecb8bf28eb 3598 * `v7->is_stashed` is non-zero
Marko Mikulicic 0:c0ecb8bf28eb 3599 */
Marko Mikulicic 0:c0ecb8bf28eb 3600 val_t stash;
Marko Mikulicic 0:c0ecb8bf28eb 3601
Marko Mikulicic 0:c0ecb8bf28eb 3602 val_t error_objects[ERROR_CTOR_MAX];
Marko Mikulicic 0:c0ecb8bf28eb 3603
Marko Mikulicic 0:c0ecb8bf28eb 3604 /*
Marko Mikulicic 0:c0ecb8bf28eb 3605 * Value that is being thrown. Valid if `is_thrown` is non-zero (see below)
Marko Mikulicic 0:c0ecb8bf28eb 3606 */
Marko Mikulicic 0:c0ecb8bf28eb 3607 val_t thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 3608
Marko Mikulicic 0:c0ecb8bf28eb 3609 /*
Marko Mikulicic 0:c0ecb8bf28eb 3610 * value that is going to be returned. Needed when some `finally` block needs
Marko Mikulicic 0:c0ecb8bf28eb 3611 * to be executed after `return my_value;` was issued. Used in bcode.
Marko Mikulicic 0:c0ecb8bf28eb 3612 * See also `is_returned` below
Marko Mikulicic 0:c0ecb8bf28eb 3613 */
Marko Mikulicic 0:c0ecb8bf28eb 3614 val_t returned_value;
Marko Mikulicic 0:c0ecb8bf28eb 3615
Marko Mikulicic 0:c0ecb8bf28eb 3616 val_t last_name[2]; /* used for error reporting */
Marko Mikulicic 0:c0ecb8bf28eb 3617 /* most recent OP_CHECK_CALL exceptions, to be thrown by OP_CALL|OP_NEW */
Marko Mikulicic 0:c0ecb8bf28eb 3618 val_t call_check_ex;
Marko Mikulicic 0:c0ecb8bf28eb 3619 };
Marko Mikulicic 0:c0ecb8bf28eb 3620
Marko Mikulicic 0:c0ecb8bf28eb 3621 struct v7 {
Marko Mikulicic 0:c0ecb8bf28eb 3622 struct v7_vals vals;
Marko Mikulicic 0:c0ecb8bf28eb 3623
Marko Mikulicic 0:c0ecb8bf28eb 3624 /*
Marko Mikulicic 0:c0ecb8bf28eb 3625 * Stack of call frames.
Marko Mikulicic 0:c0ecb8bf28eb 3626 *
Marko Mikulicic 0:c0ecb8bf28eb 3627 * Execution contexts are contained in two chains:
Marko Mikulicic 0:c0ecb8bf28eb 3628 * - Stack of call frames: to allow returning, throwing, and stack trace
Marko Mikulicic 0:c0ecb8bf28eb 3629 * generation;
Marko Mikulicic 0:c0ecb8bf28eb 3630 * - In the lexical scope via their prototype chain (to allow variable
Marko Mikulicic 0:c0ecb8bf28eb 3631 * lookup), see `struct v7_call_frame_private::scope`.
Marko Mikulicic 0:c0ecb8bf28eb 3632 *
Marko Mikulicic 0:c0ecb8bf28eb 3633 * Execution contexts should be allocated on heap, because they might not be
Marko Mikulicic 0:c0ecb8bf28eb 3634 * on a call stack but still referenced (closures).
Marko Mikulicic 0:c0ecb8bf28eb 3635 *
Marko Mikulicic 0:c0ecb8bf28eb 3636 * New call frame is created every time some top-level code is evaluated,
Marko Mikulicic 0:c0ecb8bf28eb 3637 * or some code is being `eval`-d, or some function is called, either JS
Marko Mikulicic 0:c0ecb8bf28eb 3638 * function or C function (although the call frame types are different for
Marko Mikulicic 0:c0ecb8bf28eb 3639 * JS functions and cfunctions, see `struct v7_call_frame_base` and its
Marko Mikulicic 0:c0ecb8bf28eb 3640 * sub-structures)
Marko Mikulicic 0:c0ecb8bf28eb 3641 *
Marko Mikulicic 0:c0ecb8bf28eb 3642 * When no code is being evaluated at the moment, `call_stack` is `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 3643 *
Marko Mikulicic 0:c0ecb8bf28eb 3644 * See comment for `struct v7_call_frame_base` for some more details.
Marko Mikulicic 0:c0ecb8bf28eb 3645 */
Marko Mikulicic 0:c0ecb8bf28eb 3646 struct v7_call_frame_base *call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 3647
Marko Mikulicic 0:c0ecb8bf28eb 3648 /*
Marko Mikulicic 0:c0ecb8bf28eb 3649 * Bcode executes until it reaches `bottom_call_frame`. When some top-level
Marko Mikulicic 0:c0ecb8bf28eb 3650 * or `eval`-d code starts execution, the `bottom_call_frame` is set to the
Marko Mikulicic 0:c0ecb8bf28eb 3651 * call frame which was just created for the execution.
Marko Mikulicic 0:c0ecb8bf28eb 3652 */
Marko Mikulicic 0:c0ecb8bf28eb 3653 struct v7_call_frame_base *bottom_call_frame;
Marko Mikulicic 0:c0ecb8bf28eb 3654
Marko Mikulicic 0:c0ecb8bf28eb 3655 struct mbuf stack; /* value stack for bcode interpreter */
Marko Mikulicic 0:c0ecb8bf28eb 3656
Marko Mikulicic 0:c0ecb8bf28eb 3657 struct mbuf owned_strings; /* Sequence of (varint len, char data[]) */
Marko Mikulicic 0:c0ecb8bf28eb 3658 struct mbuf foreign_strings; /* Sequence of (varint len, char *data) */
Marko Mikulicic 0:c0ecb8bf28eb 3659
Marko Mikulicic 0:c0ecb8bf28eb 3660 struct mbuf tmp_stack; /* Stack of val_t* elements, used as root set */
Marko Mikulicic 0:c0ecb8bf28eb 3661 int need_gc; /* Set to true to trigger GC when safe */
Marko Mikulicic 0:c0ecb8bf28eb 3662
Marko Mikulicic 0:c0ecb8bf28eb 3663 struct gc_arena generic_object_arena;
Marko Mikulicic 0:c0ecb8bf28eb 3664 struct gc_arena function_arena;
Marko Mikulicic 0:c0ecb8bf28eb 3665 struct gc_arena property_arena;
Marko Mikulicic 0:c0ecb8bf28eb 3666 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 3667 size_t function_arena_ast_size;
Marko Mikulicic 0:c0ecb8bf28eb 3668 size_t bcode_ops_size;
Marko Mikulicic 0:c0ecb8bf28eb 3669 size_t bcode_lit_total_size;
Marko Mikulicic 0:c0ecb8bf28eb 3670 size_t bcode_lit_deser_size;
Marko Mikulicic 0:c0ecb8bf28eb 3671 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3672 struct mbuf owned_values; /* buffer for GC roots owned by C code */
Marko Mikulicic 0:c0ecb8bf28eb 3673
Marko Mikulicic 0:c0ecb8bf28eb 3674 /*
Marko Mikulicic 0:c0ecb8bf28eb 3675 * Stack of the root bcodes being executed at the moment. Note that when some
Marko Mikulicic 0:c0ecb8bf28eb 3676 * regular JS function is called inside `eval_bcode()`, the function's bcode
Marko Mikulicic 0:c0ecb8bf28eb 3677 * is NOT added here. Buf if some cfunction is called, which in turn calls
Marko Mikulicic 0:c0ecb8bf28eb 3678 * `b_exec()` (or `b_apply()`) recursively, the new bcode is added to this
Marko Mikulicic 0:c0ecb8bf28eb 3679 * stack.
Marko Mikulicic 0:c0ecb8bf28eb 3680 */
Marko Mikulicic 0:c0ecb8bf28eb 3681 struct mbuf act_bcodes;
Marko Mikulicic 0:c0ecb8bf28eb 3682
Marko Mikulicic 0:c0ecb8bf28eb 3683 char error_msg[80]; /* Exception message */
Marko Mikulicic 0:c0ecb8bf28eb 3684
Marko Mikulicic 0:c0ecb8bf28eb 3685 struct mbuf json_visited_stack; /* Detecting cycle in to_json */
Marko Mikulicic 0:c0ecb8bf28eb 3686
Marko Mikulicic 0:c0ecb8bf28eb 3687 /* Parser state */
Marko Mikulicic 0:c0ecb8bf28eb 3688 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 3689 struct v7_pstate pstate; /* Parsing state */
Marko Mikulicic 0:c0ecb8bf28eb 3690 enum v7_tok cur_tok; /* Current token */
Marko Mikulicic 0:c0ecb8bf28eb 3691 const char *tok; /* Parsed terminal token (ident, number, string) */
Marko Mikulicic 0:c0ecb8bf28eb 3692 unsigned long tok_len; /* Length of the parsed terminal token */
Marko Mikulicic 0:c0ecb8bf28eb 3693 size_t last_var_node; /* Offset of last var node or function/script node */
Marko Mikulicic 0:c0ecb8bf28eb 3694 int after_newline; /* True if the cur_tok starts a new line */
Marko Mikulicic 0:c0ecb8bf28eb 3695 double cur_tok_dbl; /* When tokenizing, parser stores TOK_NUMBER here */
Marko Mikulicic 0:c0ecb8bf28eb 3696
Marko Mikulicic 0:c0ecb8bf28eb 3697 /*
Marko Mikulicic 0:c0ecb8bf28eb 3698 * Current linenumber. Currently it is used by parser, compiler and bcode
Marko Mikulicic 0:c0ecb8bf28eb 3699 * evaluator.
Marko Mikulicic 0:c0ecb8bf28eb 3700 *
Marko Mikulicic 0:c0ecb8bf28eb 3701 * - Parser: it's the last line_no emitted to AST
Marko Mikulicic 0:c0ecb8bf28eb 3702 * - Compiler: it's the last line_no emitted to bcode
Marko Mikulicic 0:c0ecb8bf28eb 3703 */
Marko Mikulicic 0:c0ecb8bf28eb 3704 int line_no;
Marko Mikulicic 0:c0ecb8bf28eb 3705 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 3706
Marko Mikulicic 0:c0ecb8bf28eb 3707 /* singleton, pointer because of amalgamation */
Marko Mikulicic 0:c0ecb8bf28eb 3708 struct v7_property *cur_dense_prop;
Marko Mikulicic 0:c0ecb8bf28eb 3709
Marko Mikulicic 0:c0ecb8bf28eb 3710 volatile int interrupted;
Marko Mikulicic 0:c0ecb8bf28eb 3711 #ifdef V7_STACK_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 3712 void *sp_limit;
Marko Mikulicic 0:c0ecb8bf28eb 3713 void *sp_lwm;
Marko Mikulicic 0:c0ecb8bf28eb 3714 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3715
Marko Mikulicic 0:c0ecb8bf28eb 3716 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 3717 /* linked list of v7 contexts, needed by cyg_profile hooks */
Marko Mikulicic 0:c0ecb8bf28eb 3718 struct v7 *next_v7;
Marko Mikulicic 0:c0ecb8bf28eb 3719
Marko Mikulicic 0:c0ecb8bf28eb 3720 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 3721 /* linked list of stack tracking contexts */
Marko Mikulicic 0:c0ecb8bf28eb 3722 struct stack_track_ctx *stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 3723
Marko Mikulicic 0:c0ecb8bf28eb 3724 int stack_stat[V7_STACK_STATS_CNT];
Marko Mikulicic 0:c0ecb8bf28eb 3725 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3726
Marko Mikulicic 0:c0ecb8bf28eb 3727 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3728
Marko Mikulicic 0:c0ecb8bf28eb 3729 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 3730 struct mbuf malloc_trace;
Marko Mikulicic 0:c0ecb8bf28eb 3731 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3732
Marko Mikulicic 0:c0ecb8bf28eb 3733 /*
Marko Mikulicic 0:c0ecb8bf28eb 3734 * TODO(imax): remove V7_DISABLE_STR_ALLOC_SEQ knob after 2015/12/01 if there
Marko Mikulicic 0:c0ecb8bf28eb 3735 * are no issues.
Marko Mikulicic 0:c0ecb8bf28eb 3736 */
Marko Mikulicic 0:c0ecb8bf28eb 3737 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 3738 uint16_t gc_next_asn; /* Next sequence number to use. */
Marko Mikulicic 0:c0ecb8bf28eb 3739 uint16_t gc_min_asn; /* Minimal sequence number currently in use. */
Marko Mikulicic 0:c0ecb8bf28eb 3740 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3741
Marko Mikulicic 0:c0ecb8bf28eb 3742 #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 3743 size_t parser_stack_data_max_size;
Marko Mikulicic 0:c0ecb8bf28eb 3744 size_t parser_stack_ret_max_size;
Marko Mikulicic 0:c0ecb8bf28eb 3745 size_t parser_stack_data_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 3746 size_t parser_stack_ret_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 3747 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3748
Marko Mikulicic 0:c0ecb8bf28eb 3749 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 3750 FILE *freeze_file;
Marko Mikulicic 0:c0ecb8bf28eb 3751 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3752
Marko Mikulicic 0:c0ecb8bf28eb 3753 /*
Marko Mikulicic 0:c0ecb8bf28eb 3754 * true if exception is currently being created. Needed to avoid recursive
Marko Mikulicic 0:c0ecb8bf28eb 3755 * exception creation
Marko Mikulicic 0:c0ecb8bf28eb 3756 */
Marko Mikulicic 0:c0ecb8bf28eb 3757 unsigned int creating_exception : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3758 /* while true, GC is inhibited */
Marko Mikulicic 0:c0ecb8bf28eb 3759 unsigned int inhibit_gc : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3760 /* true if `thrown_error` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 3761 unsigned int is_thrown : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3762 /* true if `returned_value` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 3763 unsigned int is_returned : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3764 /* true if a finally block is executing while breaking */
Marko Mikulicic 0:c0ecb8bf28eb 3765 unsigned int is_breaking : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3766 /* true when a continue OP is executed, reset by `OP_JMP_IF_CONTINUE` */
Marko Mikulicic 0:c0ecb8bf28eb 3767 unsigned int is_continuing : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3768 /* true if some value is currently stashed (`v7->vals.stash`) */
Marko Mikulicic 0:c0ecb8bf28eb 3769 unsigned int is_stashed : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3770 /* true if last emitted statement does not affect data stack */
Marko Mikulicic 0:c0ecb8bf28eb 3771 unsigned int is_stack_neutral : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3772 /* true if precompiling; affects compiler bcode choices */
Marko Mikulicic 0:c0ecb8bf28eb 3773 unsigned int is_precompiling : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3774
Marko Mikulicic 0:c0ecb8bf28eb 3775 enum opcode last_ops[2]; /* trace of last ops, used for error reporting */
Marko Mikulicic 0:c0ecb8bf28eb 3776 };
Marko Mikulicic 0:c0ecb8bf28eb 3777
Marko Mikulicic 0:c0ecb8bf28eb 3778 struct v7_property {
Marko Mikulicic 0:c0ecb8bf28eb 3779 struct v7_property *
Marko Mikulicic 0:c0ecb8bf28eb 3780 next; /* Linkage in struct v7_generic_object::properties */
Marko Mikulicic 0:c0ecb8bf28eb 3781 v7_prop_attr_t attributes;
Marko Mikulicic 0:c0ecb8bf28eb 3782 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 3783 entity_id_t entity_id;
Marko Mikulicic 0:c0ecb8bf28eb 3784 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3785 val_t name; /* Property name (a string) */
Marko Mikulicic 0:c0ecb8bf28eb 3786 val_t value; /* Property value */
Marko Mikulicic 0:c0ecb8bf28eb 3787 };
Marko Mikulicic 0:c0ecb8bf28eb 3788
Marko Mikulicic 0:c0ecb8bf28eb 3789 /*
Marko Mikulicic 0:c0ecb8bf28eb 3790 * "base object": structure which is shared between objects and functions.
Marko Mikulicic 0:c0ecb8bf28eb 3791 */
Marko Mikulicic 0:c0ecb8bf28eb 3792 struct v7_object {
Marko Mikulicic 0:c0ecb8bf28eb 3793 /* First HIDDEN property in a chain is an internal object value */
Marko Mikulicic 0:c0ecb8bf28eb 3794 struct v7_property *properties;
Marko Mikulicic 0:c0ecb8bf28eb 3795 v7_obj_attr_t attributes;
Marko Mikulicic 0:c0ecb8bf28eb 3796 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 3797 entity_id_part_t entity_id_base;
Marko Mikulicic 0:c0ecb8bf28eb 3798 entity_id_part_t entity_id_spec;
Marko Mikulicic 0:c0ecb8bf28eb 3799 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3800 };
Marko Mikulicic 0:c0ecb8bf28eb 3801
Marko Mikulicic 0:c0ecb8bf28eb 3802 /*
Marko Mikulicic 0:c0ecb8bf28eb 3803 * An object is an unordered collection of properties.
Marko Mikulicic 0:c0ecb8bf28eb 3804 * A function stored in a property of an object is called a method.
Marko Mikulicic 0:c0ecb8bf28eb 3805 * A property has a name, a value, and set of attributes.
Marko Mikulicic 0:c0ecb8bf28eb 3806 * Attributes are: ReadOnly, DontEnum, DontDelete, Internal.
Marko Mikulicic 0:c0ecb8bf28eb 3807 *
Marko Mikulicic 0:c0ecb8bf28eb 3808 * A constructor is a function that creates and initializes objects.
Marko Mikulicic 0:c0ecb8bf28eb 3809 * Each constructor has an associated prototype object that is used for
Marko Mikulicic 0:c0ecb8bf28eb 3810 * inheritance and shared properties. When a constructor creates an object,
Marko Mikulicic 0:c0ecb8bf28eb 3811 * the new object references the constructor’s prototype.
Marko Mikulicic 0:c0ecb8bf28eb 3812 *
Marko Mikulicic 0:c0ecb8bf28eb 3813 * Objects could be a "generic objects" which is a collection of properties,
Marko Mikulicic 0:c0ecb8bf28eb 3814 * or a "typed object" which also hold an internal value like String or Number.
Marko Mikulicic 0:c0ecb8bf28eb 3815 * Those values are implicit, unnamed properties of the respective types,
Marko Mikulicic 0:c0ecb8bf28eb 3816 * and can be coerced into primitive types by calling a respective constructor
Marko Mikulicic 0:c0ecb8bf28eb 3817 * as a function:
Marko Mikulicic 0:c0ecb8bf28eb 3818 * var a = new Number(123);
Marko Mikulicic 0:c0ecb8bf28eb 3819 * typeof(a) == 'object';
Marko Mikulicic 0:c0ecb8bf28eb 3820 * typeof(Number(a)) == 'number';
Marko Mikulicic 0:c0ecb8bf28eb 3821 */
Marko Mikulicic 0:c0ecb8bf28eb 3822 struct v7_generic_object {
Marko Mikulicic 0:c0ecb8bf28eb 3823 /*
Marko Mikulicic 0:c0ecb8bf28eb 3824 * This has to be the first field so that objects can be managed by the GC.
Marko Mikulicic 0:c0ecb8bf28eb 3825 */
Marko Mikulicic 0:c0ecb8bf28eb 3826 struct v7_object base;
Marko Mikulicic 0:c0ecb8bf28eb 3827 struct v7_object *prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3828 };
Marko Mikulicic 0:c0ecb8bf28eb 3829
Marko Mikulicic 0:c0ecb8bf28eb 3830 /*
Marko Mikulicic 0:c0ecb8bf28eb 3831 * Variables are function-scoped and are hoisted.
Marko Mikulicic 0:c0ecb8bf28eb 3832 * Lexical scoping & closures: each function has a chain of scopes, defined
Marko Mikulicic 0:c0ecb8bf28eb 3833 * by the lexicographic order of function definitions.
Marko Mikulicic 0:c0ecb8bf28eb 3834 * Scope is different from the execution context.
Marko Mikulicic 0:c0ecb8bf28eb 3835 * Execution context carries "variable object" which is variable/value
Marko Mikulicic 0:c0ecb8bf28eb 3836 * mapping for all variables defined in a function, and `this` object.
Marko Mikulicic 0:c0ecb8bf28eb 3837 * If function is not called as a method, then `this` is a global object.
Marko Mikulicic 0:c0ecb8bf28eb 3838 * Otherwise, `this` is an object that contains called method.
Marko Mikulicic 0:c0ecb8bf28eb 3839 * New execution context is created each time a function call is performed.
Marko Mikulicic 0:c0ecb8bf28eb 3840 * Passing arguments through recursion is done using execution context, e.g.
Marko Mikulicic 0:c0ecb8bf28eb 3841 *
Marko Mikulicic 0:c0ecb8bf28eb 3842 * var factorial = function(num) {
Marko Mikulicic 0:c0ecb8bf28eb 3843 * return num < 2 ? 1 : num * factorial(num - 1);
Marko Mikulicic 0:c0ecb8bf28eb 3844 * };
Marko Mikulicic 0:c0ecb8bf28eb 3845 *
Marko Mikulicic 0:c0ecb8bf28eb 3846 * Here, recursion calls the same function `factorial` several times. Execution
Marko Mikulicic 0:c0ecb8bf28eb 3847 * contexts for each call form a stack. Each context has different variable
Marko Mikulicic 0:c0ecb8bf28eb 3848 * object, `vars`, with different values of `num`.
Marko Mikulicic 0:c0ecb8bf28eb 3849 */
Marko Mikulicic 0:c0ecb8bf28eb 3850
Marko Mikulicic 0:c0ecb8bf28eb 3851 struct v7_js_function {
Marko Mikulicic 0:c0ecb8bf28eb 3852 /*
Marko Mikulicic 0:c0ecb8bf28eb 3853 * Functions are objects. This has to be the first field so that function
Marko Mikulicic 0:c0ecb8bf28eb 3854 * objects can be managed by the GC.
Marko Mikulicic 0:c0ecb8bf28eb 3855 */
Marko Mikulicic 0:c0ecb8bf28eb 3856 struct v7_object base;
Marko Mikulicic 0:c0ecb8bf28eb 3857 struct v7_generic_object *scope; /* lexical scope of the closure */
Marko Mikulicic 0:c0ecb8bf28eb 3858
Marko Mikulicic 0:c0ecb8bf28eb 3859 /* bytecode, might be shared between functions */
Marko Mikulicic 0:c0ecb8bf28eb 3860 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 3861 };
Marko Mikulicic 0:c0ecb8bf28eb 3862
Marko Mikulicic 0:c0ecb8bf28eb 3863 struct v7_regexp {
Marko Mikulicic 0:c0ecb8bf28eb 3864 val_t regexp_string;
Marko Mikulicic 0:c0ecb8bf28eb 3865 struct slre_prog *compiled_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 3866 long lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 3867 };
Marko Mikulicic 0:c0ecb8bf28eb 3868
Marko Mikulicic 0:c0ecb8bf28eb 3869 /* Vector, describes some memory location pointed by `p` with length `len` */
Marko Mikulicic 0:c0ecb8bf28eb 3870 struct v7_vec {
Marko Mikulicic 0:c0ecb8bf28eb 3871 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 3872 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 3873 };
Marko Mikulicic 0:c0ecb8bf28eb 3874
Marko Mikulicic 0:c0ecb8bf28eb 3875 /*
Marko Mikulicic 0:c0ecb8bf28eb 3876 * Constant vector, describes some const memory location pointed by `p` with
Marko Mikulicic 0:c0ecb8bf28eb 3877 * length `len`
Marko Mikulicic 0:c0ecb8bf28eb 3878 */
Marko Mikulicic 0:c0ecb8bf28eb 3879 struct v7_vec_const {
Marko Mikulicic 0:c0ecb8bf28eb 3880 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 3881 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 3882 };
Marko Mikulicic 0:c0ecb8bf28eb 3883
Marko Mikulicic 0:c0ecb8bf28eb 3884 #define V7_VEC(str) \
Marko Mikulicic 0:c0ecb8bf28eb 3885 { (str), sizeof(str) - 1 }
Marko Mikulicic 0:c0ecb8bf28eb 3886
Marko Mikulicic 0:c0ecb8bf28eb 3887 /*
Marko Mikulicic 0:c0ecb8bf28eb 3888 * Returns current execution scope.
Marko Mikulicic 0:c0ecb8bf28eb 3889 *
Marko Mikulicic 0:c0ecb8bf28eb 3890 * See comment for `struct v7_call_frame_private::vals::scope`
Marko Mikulicic 0:c0ecb8bf28eb 3891 */
Marko Mikulicic 0:c0ecb8bf28eb 3892 V7_PRIVATE v7_val_t get_scope(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 3893
Marko Mikulicic 0:c0ecb8bf28eb 3894 /*
Marko Mikulicic 0:c0ecb8bf28eb 3895 * Returns 1 if currently executing bcode in the "strict mode", 0 otherwise
Marko Mikulicic 0:c0ecb8bf28eb 3896 */
Marko Mikulicic 0:c0ecb8bf28eb 3897 V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 3898
Marko Mikulicic 0:c0ecb8bf28eb 3899 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 3900 }
Marko Mikulicic 0:c0ecb8bf28eb 3901 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 3902
Marko Mikulicic 0:c0ecb8bf28eb 3903 #endif /* CS_V7_SRC_CORE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 3904 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 3905 #line 1 "v7/src/primitive_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 3906 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3907 /*
Marko Mikulicic 0:c0ecb8bf28eb 3908 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 3909 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 3910 */
Marko Mikulicic 0:c0ecb8bf28eb 3911
Marko Mikulicic 0:c0ecb8bf28eb 3912 /*
Marko Mikulicic 0:c0ecb8bf28eb 3913 * === Primitives
Marko Mikulicic 0:c0ecb8bf28eb 3914 *
Marko Mikulicic 0:c0ecb8bf28eb 3915 * All primitive values but strings.
Marko Mikulicic 0:c0ecb8bf28eb 3916 *
Marko Mikulicic 0:c0ecb8bf28eb 3917 * "foreign" values are also here, see `v7_mk_foreign()`.
Marko Mikulicic 0:c0ecb8bf28eb 3918 */
Marko Mikulicic 0:c0ecb8bf28eb 3919
Marko Mikulicic 0:c0ecb8bf28eb 3920 #ifndef CS_V7_SRC_PRIMITIVE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 3921 #define CS_V7_SRC_PRIMITIVE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 3922
Marko Mikulicic 0:c0ecb8bf28eb 3923 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3924
Marko Mikulicic 0:c0ecb8bf28eb 3925 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 3926 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 3927 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 3928
Marko Mikulicic 0:c0ecb8bf28eb 3929 /* Make numeric primitive value */
Marko Mikulicic 0:c0ecb8bf28eb 3930 NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double num);
Marko Mikulicic 0:c0ecb8bf28eb 3931
Marko Mikulicic 0:c0ecb8bf28eb 3932 /*
Marko Mikulicic 0:c0ecb8bf28eb 3933 * Returns number value stored in `v7_val_t` as `double`.
Marko Mikulicic 0:c0ecb8bf28eb 3934 *
Marko Mikulicic 0:c0ecb8bf28eb 3935 * Returns NaN for non-numbers.
Marko Mikulicic 0:c0ecb8bf28eb 3936 */
Marko Mikulicic 0:c0ecb8bf28eb 3937 NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3938
Marko Mikulicic 0:c0ecb8bf28eb 3939 /*
Marko Mikulicic 0:c0ecb8bf28eb 3940 * Returns number value stored in `v7_val_t` as `int`. If the number value is
Marko Mikulicic 0:c0ecb8bf28eb 3941 * not an integer, the fraction part will be discarded.
Marko Mikulicic 0:c0ecb8bf28eb 3942 *
Marko Mikulicic 0:c0ecb8bf28eb 3943 * If the given value is a non-number, or NaN, the result is undefined.
Marko Mikulicic 0:c0ecb8bf28eb 3944 */
Marko Mikulicic 0:c0ecb8bf28eb 3945 NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3946
Marko Mikulicic 0:c0ecb8bf28eb 3947 /* Returns true if given value is a primitive number value */
Marko Mikulicic 0:c0ecb8bf28eb 3948 int v7_is_number(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3949
Marko Mikulicic 0:c0ecb8bf28eb 3950 /* Make boolean primitive value (either `true` or `false`) */
Marko Mikulicic 0:c0ecb8bf28eb 3951 NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int is_true);
Marko Mikulicic 0:c0ecb8bf28eb 3952
Marko Mikulicic 0:c0ecb8bf28eb 3953 /*
Marko Mikulicic 0:c0ecb8bf28eb 3954 * Returns boolean stored in `v7_val_t`:
Marko Mikulicic 0:c0ecb8bf28eb 3955 * 0 for `false` or non-boolean, non-0 for `true`
Marko Mikulicic 0:c0ecb8bf28eb 3956 */
Marko Mikulicic 0:c0ecb8bf28eb 3957 NOINSTR int v7_get_bool(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3958
Marko Mikulicic 0:c0ecb8bf28eb 3959 /* Returns true if given value is a primitive boolean value */
Marko Mikulicic 0:c0ecb8bf28eb 3960 int v7_is_boolean(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3961
Marko Mikulicic 0:c0ecb8bf28eb 3962 /*
Marko Mikulicic 0:c0ecb8bf28eb 3963 * Make `null` primitive value.
Marko Mikulicic 0:c0ecb8bf28eb 3964 *
Marko Mikulicic 0:c0ecb8bf28eb 3965 * NOTE: this function is deprecated and will be removed in future releases.
Marko Mikulicic 0:c0ecb8bf28eb 3966 * Use `V7_NULL` instead.
Marko Mikulicic 0:c0ecb8bf28eb 3967 */
Marko Mikulicic 0:c0ecb8bf28eb 3968 NOINSTR v7_val_t v7_mk_null(void);
Marko Mikulicic 0:c0ecb8bf28eb 3969
Marko Mikulicic 0:c0ecb8bf28eb 3970 /* Returns true if given value is a primitive `null` value */
Marko Mikulicic 0:c0ecb8bf28eb 3971 int v7_is_null(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3972
Marko Mikulicic 0:c0ecb8bf28eb 3973 /*
Marko Mikulicic 0:c0ecb8bf28eb 3974 * Make `undefined` primitive value.
Marko Mikulicic 0:c0ecb8bf28eb 3975 *
Marko Mikulicic 0:c0ecb8bf28eb 3976 * NOTE: this function is deprecated and will be removed in future releases.
Marko Mikulicic 0:c0ecb8bf28eb 3977 * Use `V7_UNDEFINED` instead.
Marko Mikulicic 0:c0ecb8bf28eb 3978 */
Marko Mikulicic 0:c0ecb8bf28eb 3979 NOINSTR v7_val_t v7_mk_undefined(void);
Marko Mikulicic 0:c0ecb8bf28eb 3980
Marko Mikulicic 0:c0ecb8bf28eb 3981 /* Returns true if given value is a primitive `undefined` value */
Marko Mikulicic 0:c0ecb8bf28eb 3982 int v7_is_undefined(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3983
Marko Mikulicic 0:c0ecb8bf28eb 3984 /*
Marko Mikulicic 0:c0ecb8bf28eb 3985 * Make JavaScript value that holds C/C++ `void *` pointer.
Marko Mikulicic 0:c0ecb8bf28eb 3986 *
Marko Mikulicic 0:c0ecb8bf28eb 3987 * A foreign value is completely opaque and JS code cannot do anything useful
Marko Mikulicic 0:c0ecb8bf28eb 3988 * with it except holding it in properties and passing it around.
Marko Mikulicic 0:c0ecb8bf28eb 3989 * It behaves like a sealed object with no properties.
Marko Mikulicic 0:c0ecb8bf28eb 3990 *
Marko Mikulicic 0:c0ecb8bf28eb 3991 * NOTE:
Marko Mikulicic 0:c0ecb8bf28eb 3992 * Only valid pointers (as defined by each supported architecture) will fully
Marko Mikulicic 0:c0ecb8bf28eb 3993 * preserved. In particular, all supported 64-bit architectures (x86_64, ARM-64)
Marko Mikulicic 0:c0ecb8bf28eb 3994 * actually define a 48-bit virtual address space.
Marko Mikulicic 0:c0ecb8bf28eb 3995 * Foreign values will be sign-extended as required, i.e creating a foreign
Marko Mikulicic 0:c0ecb8bf28eb 3996 * value of something like `(void *) -1` will work as expected. This is
Marko Mikulicic 0:c0ecb8bf28eb 3997 * important because in some 64-bit OSs (e.g. Solaris) the user stack grows
Marko Mikulicic 0:c0ecb8bf28eb 3998 * downwards from the end of the address space.
Marko Mikulicic 0:c0ecb8bf28eb 3999 *
Marko Mikulicic 0:c0ecb8bf28eb 4000 * If you need to store exactly sizeof(void*) bytes of raw data where
Marko Mikulicic 0:c0ecb8bf28eb 4001 * `sizeof(void*)` >= 8, please use byte arrays instead.
Marko Mikulicic 0:c0ecb8bf28eb 4002 */
Marko Mikulicic 0:c0ecb8bf28eb 4003 NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *ptr);
Marko Mikulicic 0:c0ecb8bf28eb 4004
Marko Mikulicic 0:c0ecb8bf28eb 4005 /*
Marko Mikulicic 0:c0ecb8bf28eb 4006 * Returns `void *` pointer stored in `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4007 *
Marko Mikulicic 0:c0ecb8bf28eb 4008 * Returns NULL if the value is not a foreign pointer.
Marko Mikulicic 0:c0ecb8bf28eb 4009 */
Marko Mikulicic 0:c0ecb8bf28eb 4010 NOINSTR void *v7_get_ptr(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4011
Marko Mikulicic 0:c0ecb8bf28eb 4012 /* Returns true if given value holds `void *` pointer */
Marko Mikulicic 0:c0ecb8bf28eb 4013 int v7_is_foreign(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4014
Marko Mikulicic 0:c0ecb8bf28eb 4015 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4016 }
Marko Mikulicic 0:c0ecb8bf28eb 4017 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4018
Marko Mikulicic 0:c0ecb8bf28eb 4019 #endif /* CS_V7_SRC_PRIMITIVE_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4020 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4021 #line 1 "v7/src/primitive.h"
Marko Mikulicic 0:c0ecb8bf28eb 4022 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4023 /*
Marko Mikulicic 0:c0ecb8bf28eb 4024 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4025 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4026 */
Marko Mikulicic 0:c0ecb8bf28eb 4027
Marko Mikulicic 0:c0ecb8bf28eb 4028 #ifndef CS_V7_SRC_PRIMITIVE_H_
Marko Mikulicic 0:c0ecb8bf28eb 4029 #define CS_V7_SRC_PRIMITIVE_H_
Marko Mikulicic 0:c0ecb8bf28eb 4030
Marko Mikulicic 0:c0ecb8bf28eb 4031 /* Amalgamated: #include "v7/src/primitive_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4032
Marko Mikulicic 0:c0ecb8bf28eb 4033 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4034
Marko Mikulicic 0:c0ecb8bf28eb 4035 /* Returns true if given value is a number, not NaN and not Infinity. */
Marko Mikulicic 0:c0ecb8bf28eb 4036 V7_PRIVATE int is_finite(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4037
Marko Mikulicic 0:c0ecb8bf28eb 4038 V7_PRIVATE val_t pointer_to_value(void *p);
Marko Mikulicic 0:c0ecb8bf28eb 4039 V7_PRIVATE void *get_ptr(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4040
Marko Mikulicic 0:c0ecb8bf28eb 4041 #endif /* CS_V7_SRC_PRIMITIVE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4042 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4043 #line 1 "v7/src/string_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4044 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4045 /*
Marko Mikulicic 0:c0ecb8bf28eb 4046 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4047 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4048 */
Marko Mikulicic 0:c0ecb8bf28eb 4049
Marko Mikulicic 0:c0ecb8bf28eb 4050 /*
Marko Mikulicic 0:c0ecb8bf28eb 4051 * === Strings
Marko Mikulicic 0:c0ecb8bf28eb 4052 */
Marko Mikulicic 0:c0ecb8bf28eb 4053
Marko Mikulicic 0:c0ecb8bf28eb 4054 #ifndef CS_V7_SRC_STRING_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4055 #define CS_V7_SRC_STRING_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4056
Marko Mikulicic 0:c0ecb8bf28eb 4057 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4058
Marko Mikulicic 0:c0ecb8bf28eb 4059 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4060 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4061 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4062
Marko Mikulicic 0:c0ecb8bf28eb 4063 /*
Marko Mikulicic 0:c0ecb8bf28eb 4064 * Creates a string primitive value.
Marko Mikulicic 0:c0ecb8bf28eb 4065 * `str` must point to the utf8 string of length `len`.
Marko Mikulicic 0:c0ecb8bf28eb 4066 * If `len` is ~0, `str` is assumed to be NUL-terminated and `strlen(str)` is
Marko Mikulicic 0:c0ecb8bf28eb 4067 * used.
Marko Mikulicic 0:c0ecb8bf28eb 4068 *
Marko Mikulicic 0:c0ecb8bf28eb 4069 * If `copy` is non-zero, the string data is copied and owned by the GC. The
Marko Mikulicic 0:c0ecb8bf28eb 4070 * caller can free the string data afterwards. Otherwise (`copy` is zero), the
Marko Mikulicic 0:c0ecb8bf28eb 4071 * caller owns the string data, and is responsible for not freeing it while it
Marko Mikulicic 0:c0ecb8bf28eb 4072 * is used.
Marko Mikulicic 0:c0ecb8bf28eb 4073 */
Marko Mikulicic 0:c0ecb8bf28eb 4074 v7_val_t v7_mk_string(struct v7 *v7, const char *str, size_t len, int copy);
Marko Mikulicic 0:c0ecb8bf28eb 4075
Marko Mikulicic 0:c0ecb8bf28eb 4076 /* Returns true if given value is a primitive string value */
Marko Mikulicic 0:c0ecb8bf28eb 4077 int v7_is_string(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4078
Marko Mikulicic 0:c0ecb8bf28eb 4079 /*
Marko Mikulicic 0:c0ecb8bf28eb 4080 * Returns a pointer to the string stored in `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4081 *
Marko Mikulicic 0:c0ecb8bf28eb 4082 * String length returned in `len`, which is allowed to be NULL. Returns NULL
Marko Mikulicic 0:c0ecb8bf28eb 4083 * if the value is not a string.
Marko Mikulicic 0:c0ecb8bf28eb 4084 *
Marko Mikulicic 0:c0ecb8bf28eb 4085 * JS strings can contain embedded NUL chars and may or may not be NUL
Marko Mikulicic 0:c0ecb8bf28eb 4086 * terminated.
Marko Mikulicic 0:c0ecb8bf28eb 4087 *
Marko Mikulicic 0:c0ecb8bf28eb 4088 * CAUTION: creating new JavaScript object, array, or string may kick in a
Marko Mikulicic 0:c0ecb8bf28eb 4089 * garbage collector, which in turn may relocate string data and invalidate
Marko Mikulicic 0:c0ecb8bf28eb 4090 * pointer returned by `v7_get_string()`.
Marko Mikulicic 0:c0ecb8bf28eb 4091 *
Marko Mikulicic 0:c0ecb8bf28eb 4092 * Short JS strings are embedded inside the `v7_val_t` value itself. This is why
Marko Mikulicic 0:c0ecb8bf28eb 4093 * a pointer to a `v7_val_t` is required. It also means that the string data
Marko Mikulicic 0:c0ecb8bf28eb 4094 * will become invalid once that `v7_val_t` value goes out of scope.
Marko Mikulicic 0:c0ecb8bf28eb 4095 */
Marko Mikulicic 0:c0ecb8bf28eb 4096 const char *v7_get_string(struct v7 *v7, v7_val_t *v, size_t *len);
Marko Mikulicic 0:c0ecb8bf28eb 4097
Marko Mikulicic 0:c0ecb8bf28eb 4098 /*
Marko Mikulicic 0:c0ecb8bf28eb 4099 * Returns a pointer to the string stored in `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4100 *
Marko Mikulicic 0:c0ecb8bf28eb 4101 * Returns NULL if the value is not a string or if the string is not compatible
Marko Mikulicic 0:c0ecb8bf28eb 4102 * with a C string.
Marko Mikulicic 0:c0ecb8bf28eb 4103 *
Marko Mikulicic 0:c0ecb8bf28eb 4104 * C compatible strings contain exactly one NUL char, in terminal position.
Marko Mikulicic 0:c0ecb8bf28eb 4105 *
Marko Mikulicic 0:c0ecb8bf28eb 4106 * All strings owned by the V7 engine (see `v7_mk_string()`) are guaranteed to
Marko Mikulicic 0:c0ecb8bf28eb 4107 * be NUL terminated. Out of these, those that don't include embedded NUL chars
Marko Mikulicic 0:c0ecb8bf28eb 4108 * are guaranteed to be C compatible.
Marko Mikulicic 0:c0ecb8bf28eb 4109 */
Marko Mikulicic 0:c0ecb8bf28eb 4110 const char *v7_get_cstring(struct v7 *v7, v7_val_t *v);
Marko Mikulicic 0:c0ecb8bf28eb 4111
Marko Mikulicic 0:c0ecb8bf28eb 4112 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4113 }
Marko Mikulicic 0:c0ecb8bf28eb 4114 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4115
Marko Mikulicic 0:c0ecb8bf28eb 4116 #endif /* CS_V7_SRC_STRING_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4117 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4118 #line 1 "v7/src/string.h"
Marko Mikulicic 0:c0ecb8bf28eb 4119 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4120 /*
Marko Mikulicic 0:c0ecb8bf28eb 4121 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4122 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4123 */
Marko Mikulicic 0:c0ecb8bf28eb 4124
Marko Mikulicic 0:c0ecb8bf28eb 4125 #ifndef CS_V7_SRC_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 4126 #define CS_V7_SRC_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 4127
Marko Mikulicic 0:c0ecb8bf28eb 4128 /* Amalgamated: #include "v7/src/string_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4129
Marko Mikulicic 0:c0ecb8bf28eb 4130 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4131
Marko Mikulicic 0:c0ecb8bf28eb 4132 /*
Marko Mikulicic 0:c0ecb8bf28eb 4133 * Size of the extra space for strings mbuf that is needed to avoid frequent
Marko Mikulicic 0:c0ecb8bf28eb 4134 * reallocations
Marko Mikulicic 0:c0ecb8bf28eb 4135 */
Marko Mikulicic 0:c0ecb8bf28eb 4136 #define _V7_STRING_BUF_RESERVE 500
Marko Mikulicic 0:c0ecb8bf28eb 4137
Marko Mikulicic 0:c0ecb8bf28eb 4138 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4139 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4140 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4141
Marko Mikulicic 0:c0ecb8bf28eb 4142 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4143 V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, v7_val_t s, v7_val_t at,
Marko Mikulicic 0:c0ecb8bf28eb 4144 double *res);
Marko Mikulicic 0:c0ecb8bf28eb 4145 V7_PRIVATE int s_cmp(struct v7 *, val_t a, val_t b);
Marko Mikulicic 0:c0ecb8bf28eb 4146 V7_PRIVATE val_t s_concat(struct v7 *, val_t, val_t);
Marko Mikulicic 0:c0ecb8bf28eb 4147
Marko Mikulicic 0:c0ecb8bf28eb 4148 /*
Marko Mikulicic 0:c0ecb8bf28eb 4149 * Convert a C string to to an unsigned integer.
Marko Mikulicic 0:c0ecb8bf28eb 4150 * `ok` will be set to true if the string conforms to
Marko Mikulicic 0:c0ecb8bf28eb 4151 * an unsigned long.
Marko Mikulicic 0:c0ecb8bf28eb 4152 */
Marko Mikulicic 0:c0ecb8bf28eb 4153 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4154 V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok,
Marko Mikulicic 0:c0ecb8bf28eb 4155 unsigned long *res);
Marko Mikulicic 0:c0ecb8bf28eb 4156
Marko Mikulicic 0:c0ecb8bf28eb 4157 /*
Marko Mikulicic 0:c0ecb8bf28eb 4158 * Convert a V7 string to to an unsigned integer.
Marko Mikulicic 0:c0ecb8bf28eb 4159 * `ok` will be set to true if the string conforms to
Marko Mikulicic 0:c0ecb8bf28eb 4160 * an unsigned long.
Marko Mikulicic 0:c0ecb8bf28eb 4161 *
Marko Mikulicic 0:c0ecb8bf28eb 4162 * Use it if only you need strong conformity of the value to an integer;
Marko Mikulicic 0:c0ecb8bf28eb 4163 * otherwise, use `to_long()` or `to_number_v()` instead.
Marko Mikulicic 0:c0ecb8bf28eb 4164 */
Marko Mikulicic 0:c0ecb8bf28eb 4165 V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok);
Marko Mikulicic 0:c0ecb8bf28eb 4166
Marko Mikulicic 0:c0ecb8bf28eb 4167 enum embstr_flags {
Marko Mikulicic 0:c0ecb8bf28eb 4168 EMBSTR_ZERO_TERM = (1 << 0),
Marko Mikulicic 0:c0ecb8bf28eb 4169 EMBSTR_UNESCAPE = (1 << 1),
Marko Mikulicic 0:c0ecb8bf28eb 4170 };
Marko Mikulicic 0:c0ecb8bf28eb 4171
Marko Mikulicic 0:c0ecb8bf28eb 4172 V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p,
Marko Mikulicic 0:c0ecb8bf28eb 4173 size_t len, uint8_t /*enum embstr_flags*/ flags);
Marko Mikulicic 0:c0ecb8bf28eb 4174
Marko Mikulicic 0:c0ecb8bf28eb 4175 V7_PRIVATE size_t unescape(const char *s, size_t len, char *to);
Marko Mikulicic 0:c0ecb8bf28eb 4176
Marko Mikulicic 0:c0ecb8bf28eb 4177 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4178 }
Marko Mikulicic 0:c0ecb8bf28eb 4179 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4180
Marko Mikulicic 0:c0ecb8bf28eb 4181 #endif /* CS_V7_SRC_STRING_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4182 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4183 #line 1 "v7/src/exceptions_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4184 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4185 /*
Marko Mikulicic 0:c0ecb8bf28eb 4186 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4187 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4188 */
Marko Mikulicic 0:c0ecb8bf28eb 4189
Marko Mikulicic 0:c0ecb8bf28eb 4190 /*
Marko Mikulicic 0:c0ecb8bf28eb 4191 * === Exceptions
Marko Mikulicic 0:c0ecb8bf28eb 4192 */
Marko Mikulicic 0:c0ecb8bf28eb 4193
Marko Mikulicic 0:c0ecb8bf28eb 4194 #ifndef CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4195 #define CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4196
Marko Mikulicic 0:c0ecb8bf28eb 4197 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4198
Marko Mikulicic 0:c0ecb8bf28eb 4199 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4200 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4201 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4202
Marko Mikulicic 0:c0ecb8bf28eb 4203 /* Throw an exception with an already existing value. */
Marko Mikulicic 0:c0ecb8bf28eb 4204 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4205 enum v7_err v7_throw(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4206
Marko Mikulicic 0:c0ecb8bf28eb 4207 /*
Marko Mikulicic 0:c0ecb8bf28eb 4208 * Throw an exception with given formatted message.
Marko Mikulicic 0:c0ecb8bf28eb 4209 *
Marko Mikulicic 0:c0ecb8bf28eb 4210 * Pass "Error" as typ for a generic error.
Marko Mikulicic 0:c0ecb8bf28eb 4211 */
Marko Mikulicic 0:c0ecb8bf28eb 4212 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4213 enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, ...);
Marko Mikulicic 0:c0ecb8bf28eb 4214
Marko Mikulicic 0:c0ecb8bf28eb 4215 /*
Marko Mikulicic 0:c0ecb8bf28eb 4216 * Rethrow the currently thrown object. In fact, it just returns
Marko Mikulicic 0:c0ecb8bf28eb 4217 * V7_EXEC_EXCEPTION.
Marko Mikulicic 0:c0ecb8bf28eb 4218 */
Marko Mikulicic 0:c0ecb8bf28eb 4219 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4220 enum v7_err v7_rethrow(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4221
Marko Mikulicic 0:c0ecb8bf28eb 4222 /*
Marko Mikulicic 0:c0ecb8bf28eb 4223 * Returns the value that is being thrown at the moment, or `undefined` if
Marko Mikulicic 0:c0ecb8bf28eb 4224 * nothing is being thrown. If `is_thrown` is not `NULL`, it will be set
Marko Mikulicic 0:c0ecb8bf28eb 4225 * to either 0 or 1, depending on whether something is thrown at the moment.
Marko Mikulicic 0:c0ecb8bf28eb 4226 */
Marko Mikulicic 0:c0ecb8bf28eb 4227 v7_val_t v7_get_thrown_value(struct v7 *v7, unsigned char *is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 4228
Marko Mikulicic 0:c0ecb8bf28eb 4229 /* Clears currently thrown value, if any. */
Marko Mikulicic 0:c0ecb8bf28eb 4230 void v7_clear_thrown_value(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4231
Marko Mikulicic 0:c0ecb8bf28eb 4232 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4233 }
Marko Mikulicic 0:c0ecb8bf28eb 4234 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4235
Marko Mikulicic 0:c0ecb8bf28eb 4236 #endif /* CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4237 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4238 #line 1 "v7/src/exceptions.h"
Marko Mikulicic 0:c0ecb8bf28eb 4239 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4240 /*
Marko Mikulicic 0:c0ecb8bf28eb 4241 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4242 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4243 */
Marko Mikulicic 0:c0ecb8bf28eb 4244
Marko Mikulicic 0:c0ecb8bf28eb 4245 #ifndef CS_V7_SRC_EXCEPTIONS_H_
Marko Mikulicic 0:c0ecb8bf28eb 4246 #define CS_V7_SRC_EXCEPTIONS_H_
Marko Mikulicic 0:c0ecb8bf28eb 4247
Marko Mikulicic 0:c0ecb8bf28eb 4248 /* Amalgamated: #include "v7/src/exceptions_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4249
Marko Mikulicic 0:c0ecb8bf28eb 4250 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4251
Marko Mikulicic 0:c0ecb8bf28eb 4252 /*
Marko Mikulicic 0:c0ecb8bf28eb 4253 * Try to perform some arbitrary call, and if the result is other than `V7_OK`,
Marko Mikulicic 0:c0ecb8bf28eb 4254 * "throws" an error with `V7_THROW()`
Marko Mikulicic 0:c0ecb8bf28eb 4255 */
Marko Mikulicic 0:c0ecb8bf28eb 4256 #define V7_TRY2(call, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4257 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4258 enum v7_err _e = call; \
Marko Mikulicic 0:c0ecb8bf28eb 4259 V7_CHECK2(_e == V7_OK, _e, clean_label); \
Marko Mikulicic 0:c0ecb8bf28eb 4260 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4261
Marko Mikulicic 0:c0ecb8bf28eb 4262 /*
Marko Mikulicic 0:c0ecb8bf28eb 4263 * Sets return value to the provided one, and `goto`s `clean`.
Marko Mikulicic 0:c0ecb8bf28eb 4264 *
Marko Mikulicic 0:c0ecb8bf28eb 4265 * For this to work, you should have local `enum v7_err rcode` variable,
Marko Mikulicic 0:c0ecb8bf28eb 4266 * and a `clean` label.
Marko Mikulicic 0:c0ecb8bf28eb 4267 */
Marko Mikulicic 0:c0ecb8bf28eb 4268 #define V7_THROW2(err_code, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4269 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4270 (void) v7; \
Marko Mikulicic 0:c0ecb8bf28eb 4271 rcode = (err_code); \
Marko Mikulicic 0:c0ecb8bf28eb 4272 assert(rcode != V7_OK); \
Marko Mikulicic 0:c0ecb8bf28eb 4273 assert(!v7_is_undefined(v7->vals.thrown_error) && v7->is_thrown); \
Marko Mikulicic 0:c0ecb8bf28eb 4274 goto clean_label; \
Marko Mikulicic 0:c0ecb8bf28eb 4275 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4276
Marko Mikulicic 0:c0ecb8bf28eb 4277 /*
Marko Mikulicic 0:c0ecb8bf28eb 4278 * Checks provided condition `cond`, and if it's false, then "throws"
Marko Mikulicic 0:c0ecb8bf28eb 4279 * provided `err_code` (see `V7_THROW()`)
Marko Mikulicic 0:c0ecb8bf28eb 4280 */
Marko Mikulicic 0:c0ecb8bf28eb 4281 #define V7_CHECK2(cond, err_code, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4282 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4283 if (!(cond)) { \
Marko Mikulicic 0:c0ecb8bf28eb 4284 V7_THROW2(err_code, clean_label); \
Marko Mikulicic 0:c0ecb8bf28eb 4285 } \
Marko Mikulicic 0:c0ecb8bf28eb 4286 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4287
Marko Mikulicic 0:c0ecb8bf28eb 4288 /*
Marko Mikulicic 0:c0ecb8bf28eb 4289 * Checks provided condition `cond`, and if it's false, then "throws"
Marko Mikulicic 0:c0ecb8bf28eb 4290 * internal error
Marko Mikulicic 0:c0ecb8bf28eb 4291 *
Marko Mikulicic 0:c0ecb8bf28eb 4292 * TODO(dfrank): it would be good to have formatted string: then, we can
Marko Mikulicic 0:c0ecb8bf28eb 4293 * specify file and line.
Marko Mikulicic 0:c0ecb8bf28eb 4294 */
Marko Mikulicic 0:c0ecb8bf28eb 4295 #define V7_CHECK_INTERNAL2(cond, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4296 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4297 if (!(cond)) { \
Marko Mikulicic 0:c0ecb8bf28eb 4298 enum v7_err __rcode = v7_throwf(v7, "Error", "Internal error"); \
Marko Mikulicic 0:c0ecb8bf28eb 4299 (void) __rcode; \
Marko Mikulicic 0:c0ecb8bf28eb 4300 V7_THROW2(V7_INTERNAL_ERROR, clean_label); \
Marko Mikulicic 0:c0ecb8bf28eb 4301 } \
Marko Mikulicic 0:c0ecb8bf28eb 4302 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4303
Marko Mikulicic 0:c0ecb8bf28eb 4304 /*
Marko Mikulicic 0:c0ecb8bf28eb 4305 * Shortcuts for the macros above, but they assume the clean label `clean`.
Marko Mikulicic 0:c0ecb8bf28eb 4306 */
Marko Mikulicic 0:c0ecb8bf28eb 4307
Marko Mikulicic 0:c0ecb8bf28eb 4308 #define V7_TRY(call) V7_TRY2(call, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4309 #define V7_THROW(err_code) V7_THROW2(err_code, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4310 #define V7_CHECK(cond, err_code) V7_CHECK2(cond, err_code, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4311 #define V7_CHECK_INTERNAL(cond) V7_CHECK_INTERNAL2(cond, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4312
Marko Mikulicic 0:c0ecb8bf28eb 4313 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4314 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4315 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4316
Marko Mikulicic 0:c0ecb8bf28eb 4317 /*
Marko Mikulicic 0:c0ecb8bf28eb 4318 * At the moment, most of the exception-related functions are public, and are
Marko Mikulicic 0:c0ecb8bf28eb 4319 * declared in `exceptions_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 4320 */
Marko Mikulicic 0:c0ecb8bf28eb 4321
Marko Mikulicic 0:c0ecb8bf28eb 4322 /*
Marko Mikulicic 0:c0ecb8bf28eb 4323 * Create an instance of the exception with type `typ` (see `TYPE_ERROR`,
Marko Mikulicic 0:c0ecb8bf28eb 4324 * `SYNTAX_ERROR`, etc), and message `msg`.
Marko Mikulicic 0:c0ecb8bf28eb 4325 */
Marko Mikulicic 0:c0ecb8bf28eb 4326 V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ,
Marko Mikulicic 0:c0ecb8bf28eb 4327 const char *msg, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4328
Marko Mikulicic 0:c0ecb8bf28eb 4329 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4330 }
Marko Mikulicic 0:c0ecb8bf28eb 4331 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4332
Marko Mikulicic 0:c0ecb8bf28eb 4333 #endif /* CS_V7_SRC_EXCEPTIONS_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4334 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4335 #line 1 "v7/src/object.h"
Marko Mikulicic 0:c0ecb8bf28eb 4336 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4337 /*
Marko Mikulicic 0:c0ecb8bf28eb 4338 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4339 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4340 */
Marko Mikulicic 0:c0ecb8bf28eb 4341
Marko Mikulicic 0:c0ecb8bf28eb 4342 #ifndef CS_V7_SRC_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 4343 #define CS_V7_SRC_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 4344
Marko Mikulicic 0:c0ecb8bf28eb 4345 /* Amalgamated: #include "v7/src/object_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4346
Marko Mikulicic 0:c0ecb8bf28eb 4347 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4348 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4349
Marko Mikulicic 0:c0ecb8bf28eb 4350 V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype);
Marko Mikulicic 0:c0ecb8bf28eb 4351 V7_PRIVATE val_t v7_object_to_value(struct v7_object *o);
Marko Mikulicic 0:c0ecb8bf28eb 4352 V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4353
Marko Mikulicic 0:c0ecb8bf28eb 4354 /*
Marko Mikulicic 0:c0ecb8bf28eb 4355 * Returns pointer to the struct representing an object.
Marko Mikulicic 0:c0ecb8bf28eb 4356 * Given value must be an object (the caller can verify it
Marko Mikulicic 0:c0ecb8bf28eb 4357 * by calling `v7_is_object()`)
Marko Mikulicic 0:c0ecb8bf28eb 4358 */
Marko Mikulicic 0:c0ecb8bf28eb 4359 V7_PRIVATE struct v7_object *get_object_struct(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4360
Marko Mikulicic 0:c0ecb8bf28eb 4361 /*
Marko Mikulicic 0:c0ecb8bf28eb 4362 * Return true if given value is a JavaScript object (will return
Marko Mikulicic 0:c0ecb8bf28eb 4363 * false for function)
Marko Mikulicic 0:c0ecb8bf28eb 4364 */
Marko Mikulicic 0:c0ecb8bf28eb 4365 V7_PRIVATE int v7_is_generic_object(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4366
Marko Mikulicic 0:c0ecb8bf28eb 4367 V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4368
Marko Mikulicic 0:c0ecb8bf28eb 4369 V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4370 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4371 size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 4372 v7_prop_attr_t attrs);
Marko Mikulicic 0:c0ecb8bf28eb 4373
Marko Mikulicic 0:c0ecb8bf28eb 4374 V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4375 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4376 size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 4377
Marko Mikulicic 0:c0ecb8bf28eb 4378 /*
Marko Mikulicic 0:c0ecb8bf28eb 4379 * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated
Marko Mikulicic 0:c0ecb8bf28eb 4380 *
Marko Mikulicic 0:c0ecb8bf28eb 4381 * Returns a pointer to the property structure, given an object and a name of
Marko Mikulicic 0:c0ecb8bf28eb 4382 * the property as a pointer to string buffer and length.
Marko Mikulicic 0:c0ecb8bf28eb 4383 *
Marko Mikulicic 0:c0ecb8bf28eb 4384 * See also `v7_get_property_v`
Marko Mikulicic 0:c0ecb8bf28eb 4385 */
Marko Mikulicic 0:c0ecb8bf28eb 4386 V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4387 const char *name, size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 4388
Marko Mikulicic 0:c0ecb8bf28eb 4389 /*
Marko Mikulicic 0:c0ecb8bf28eb 4390 * Just like `v7_get_property`, but takes name as a `v7_val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4391 */
Marko Mikulicic 0:c0ecb8bf28eb 4392 V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4393 v7_val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 4394 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4395
Marko Mikulicic 0:c0ecb8bf28eb 4396 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4397 V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4398 v7_val_t name, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4399
Marko Mikulicic 0:c0ecb8bf28eb 4400 V7_PRIVATE void v7_destroy_property(struct v7_property **p);
Marko Mikulicic 0:c0ecb8bf28eb 4401
Marko Mikulicic 0:c0ecb8bf28eb 4402 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4403 V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop,
Marko Mikulicic 0:c0ecb8bf28eb 4404 val_t obj, val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 4405
Marko Mikulicic 0:c0ecb8bf28eb 4406 /*
Marko Mikulicic 0:c0ecb8bf28eb 4407 * Like `set_property`, but takes property name as a `val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4408 */
Marko Mikulicic 0:c0ecb8bf28eb 4409 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4410 V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 4411 val_t val, struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4412
Marko Mikulicic 0:c0ecb8bf28eb 4413 /*
Marko Mikulicic 0:c0ecb8bf28eb 4414 * Like JavaScript assignment: set a property with given `name` + `len` at
Marko Mikulicic 0:c0ecb8bf28eb 4415 * the object `obj` to value `val`. Returns a property through the `res`
Marko Mikulicic 0:c0ecb8bf28eb 4416 * (which may be `NULL` if return value is not required)
Marko Mikulicic 0:c0ecb8bf28eb 4417 */
Marko Mikulicic 0:c0ecb8bf28eb 4418 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4419 V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4420 size_t len, v7_val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 4421 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4422
Marko Mikulicic 0:c0ecb8bf28eb 4423 /*
Marko Mikulicic 0:c0ecb8bf28eb 4424 * Like `def_property()`, but takes property name as a `val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4425 */
Marko Mikulicic 0:c0ecb8bf28eb 4426 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4427 V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 4428 v7_prop_attr_desc_t attrs_desc, val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 4429 uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 4430 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4431
Marko Mikulicic 0:c0ecb8bf28eb 4432 /*
Marko Mikulicic 0:c0ecb8bf28eb 4433 * Define object property, similar to JavaScript `Object.defineProperty()`.
Marko Mikulicic 0:c0ecb8bf28eb 4434 *
Marko Mikulicic 0:c0ecb8bf28eb 4435 * Just like public `v7_def()`, but returns `enum v7_err`, and therefore can
Marko Mikulicic 0:c0ecb8bf28eb 4436 * throw.
Marko Mikulicic 0:c0ecb8bf28eb 4437 *
Marko Mikulicic 0:c0ecb8bf28eb 4438 * Additionally, takes param `as_assign`: if it is non-zero, it behaves
Marko Mikulicic 0:c0ecb8bf28eb 4439 * similarly to plain JavaScript assignment in terms of some exception-related
Marko Mikulicic 0:c0ecb8bf28eb 4440 * corner cases.
Marko Mikulicic 0:c0ecb8bf28eb 4441 *
Marko Mikulicic 0:c0ecb8bf28eb 4442 * `res` may be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4443 */
Marko Mikulicic 0:c0ecb8bf28eb 4444 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4445 V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4446 size_t len, v7_prop_attr_desc_t attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 4447 v7_val_t val, uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 4448 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4449
Marko Mikulicic 0:c0ecb8bf28eb 4450 V7_PRIVATE int set_method(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4451 v7_cfunction_t *func, int num_args);
Marko Mikulicic 0:c0ecb8bf28eb 4452
Marko Mikulicic 0:c0ecb8bf28eb 4453 V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4454 v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 4455
Marko Mikulicic 0:c0ecb8bf28eb 4456 /* Return address of property value or NULL if the passed property is NULL */
Marko Mikulicic 0:c0ecb8bf28eb 4457 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4458 V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4459 struct v7_property *p, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4460
Marko Mikulicic 0:c0ecb8bf28eb 4461 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 4462 /*
Marko Mikulicic 0:c0ecb8bf28eb 4463 * Additional context for property iteration of a proxied object, see
Marko Mikulicic 0:c0ecb8bf28eb 4464 * `v7_next_prop()`.
Marko Mikulicic 0:c0ecb8bf28eb 4465 */
Marko Mikulicic 0:c0ecb8bf28eb 4466 struct prop_iter_proxy_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 4467 /* Proxy target object */
Marko Mikulicic 0:c0ecb8bf28eb 4468 v7_val_t target_obj;
Marko Mikulicic 0:c0ecb8bf28eb 4469 /* Proxy handler object */
Marko Mikulicic 0:c0ecb8bf28eb 4470 v7_val_t handler_obj;
Marko Mikulicic 0:c0ecb8bf28eb 4471
Marko Mikulicic 0:c0ecb8bf28eb 4472 /*
Marko Mikulicic 0:c0ecb8bf28eb 4473 * array returned by the `ownKeys` callback, valid if only `has_own_keys` is
Marko Mikulicic 0:c0ecb8bf28eb 4474 * set
Marko Mikulicic 0:c0ecb8bf28eb 4475 */
Marko Mikulicic 0:c0ecb8bf28eb 4476 v7_val_t own_keys;
Marko Mikulicic 0:c0ecb8bf28eb 4477 /*
Marko Mikulicic 0:c0ecb8bf28eb 4478 * callback to get property descriptor, one of these:
Marko Mikulicic 0:c0ecb8bf28eb 4479 * - a JS or cfunction `getOwnPropertyDescriptor`
Marko Mikulicic 0:c0ecb8bf28eb 4480 * (if `has_get_own_prop_desc_C` is not set);
Marko Mikulicic 0:c0ecb8bf28eb 4481 * - a C callback `v7_get_own_prop_desc_cb_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4482 * (if `has_get_own_prop_desc_C` is set);
Marko Mikulicic 0:c0ecb8bf28eb 4483 */
Marko Mikulicic 0:c0ecb8bf28eb 4484 v7_val_t get_own_prop_desc;
Marko Mikulicic 0:c0ecb8bf28eb 4485
Marko Mikulicic 0:c0ecb8bf28eb 4486 /*
Marko Mikulicic 0:c0ecb8bf28eb 4487 * if `has_own_keys` is set, `own_key_idx` represents next index in the
Marko Mikulicic 0:c0ecb8bf28eb 4488 * `own_keys` array
Marko Mikulicic 0:c0ecb8bf28eb 4489 */
Marko Mikulicic 0:c0ecb8bf28eb 4490 unsigned own_key_idx : 29;
Marko Mikulicic 0:c0ecb8bf28eb 4491
Marko Mikulicic 0:c0ecb8bf28eb 4492 /* if set, `own_keys` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 4493 unsigned has_own_keys : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4494 /* if set, `get_own_prop_desc` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 4495 unsigned has_get_own_prop_desc : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4496 /*
Marko Mikulicic 0:c0ecb8bf28eb 4497 * if set, `get_own_prop_desc` is a C callback `has_get_own_prop_desc_C`, not
Marko Mikulicic 0:c0ecb8bf28eb 4498 * a JS callback
Marko Mikulicic 0:c0ecb8bf28eb 4499 */
Marko Mikulicic 0:c0ecb8bf28eb 4500 unsigned has_get_own_prop_desc_C : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4501 };
Marko Mikulicic 0:c0ecb8bf28eb 4502 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4503
Marko Mikulicic 0:c0ecb8bf28eb 4504 /*
Marko Mikulicic 0:c0ecb8bf28eb 4505 * Like public function `v7_init_prop_iter_ctx()`, but it takes additional
Marko Mikulicic 0:c0ecb8bf28eb 4506 * argument `proxy_transp`; if it is zero, and the given `obj` is a Proxy, it
Marko Mikulicic 0:c0ecb8bf28eb 4507 * will iterate the properties of the proxy itself, not the Proxy's target.
Marko Mikulicic 0:c0ecb8bf28eb 4508 */
Marko Mikulicic 0:c0ecb8bf28eb 4509 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4510 V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4511 int proxy_transp,
Marko Mikulicic 0:c0ecb8bf28eb 4512 struct prop_iter_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 4513
Marko Mikulicic 0:c0ecb8bf28eb 4514 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4515 V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx,
Marko Mikulicic 0:c0ecb8bf28eb 4516 v7_val_t *name, v7_val_t *value,
Marko Mikulicic 0:c0ecb8bf28eb 4517 v7_prop_attr_t *attrs, int *ok);
Marko Mikulicic 0:c0ecb8bf28eb 4518
Marko Mikulicic 0:c0ecb8bf28eb 4519 /*
Marko Mikulicic 0:c0ecb8bf28eb 4520 * Set new prototype `proto` for the given object `obj`. Returns `0` at
Marko Mikulicic 0:c0ecb8bf28eb 4521 * success, `-1` at failure (it may fail if given `obj` is a function object:
Marko Mikulicic 0:c0ecb8bf28eb 4522 * it's impossible to change function object's prototype)
Marko Mikulicic 0:c0ecb8bf28eb 4523 */
Marko Mikulicic 0:c0ecb8bf28eb 4524 V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj,
Marko Mikulicic 0:c0ecb8bf28eb 4525 struct v7_object *proto);
Marko Mikulicic 0:c0ecb8bf28eb 4526
Marko Mikulicic 0:c0ecb8bf28eb 4527 /*
Marko Mikulicic 0:c0ecb8bf28eb 4528 * Given a pointer to the object structure, returns a
Marko Mikulicic 0:c0ecb8bf28eb 4529 * pointer to the prototype object, or `NULL` if there is
Marko Mikulicic 0:c0ecb8bf28eb 4530 * no prototype.
Marko Mikulicic 0:c0ecb8bf28eb 4531 */
Marko Mikulicic 0:c0ecb8bf28eb 4532 V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 4533 struct v7_object *obj);
Marko Mikulicic 0:c0ecb8bf28eb 4534
Marko Mikulicic 0:c0ecb8bf28eb 4535 V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p);
Marko Mikulicic 0:c0ecb8bf28eb 4536
Marko Mikulicic 0:c0ecb8bf28eb 4537 /* Get the property holding user data and destructor, or NULL */
Marko Mikulicic 0:c0ecb8bf28eb 4538 V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj);
Marko Mikulicic 0:c0ecb8bf28eb 4539
Marko Mikulicic 0:c0ecb8bf28eb 4540 #endif /* CS_V7_SRC_OBJECT_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4541 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4542 #line 1 "v7/src/exec_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4543 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4544 /*
Marko Mikulicic 0:c0ecb8bf28eb 4545 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4546 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4547 */
Marko Mikulicic 0:c0ecb8bf28eb 4548
Marko Mikulicic 0:c0ecb8bf28eb 4549 /*
Marko Mikulicic 0:c0ecb8bf28eb 4550 * === Execution of JavaScript code
Marko Mikulicic 0:c0ecb8bf28eb 4551 */
Marko Mikulicic 0:c0ecb8bf28eb 4552
Marko Mikulicic 0:c0ecb8bf28eb 4553 #ifndef CS_V7_SRC_EXEC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4554 #define CS_V7_SRC_EXEC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4555
Marko Mikulicic 0:c0ecb8bf28eb 4556 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4557
Marko Mikulicic 2:7762b98d31c7 4558 #if defined(__cplusplus)
Marko Mikulicic 2:7762b98d31c7 4559 extern "C" {
Marko Mikulicic 2:7762b98d31c7 4560 #endif /* __cplusplus */
Marko Mikulicic 2:7762b98d31c7 4561
Marko Mikulicic 0:c0ecb8bf28eb 4562 /*
Marko Mikulicic 0:c0ecb8bf28eb 4563 * Execute JavaScript `js_code`. The result of evaluation is stored in
Marko Mikulicic 0:c0ecb8bf28eb 4564 * the `result` variable.
Marko Mikulicic 0:c0ecb8bf28eb 4565 *
Marko Mikulicic 0:c0ecb8bf28eb 4566 * Return:
Marko Mikulicic 0:c0ecb8bf28eb 4567 *
Marko Mikulicic 0:c0ecb8bf28eb 4568 * - V7_OK on success. `result` contains the result of execution.
Marko Mikulicic 0:c0ecb8bf28eb 4569 * - V7_SYNTAX_ERROR if `js_code` in not a valid code. `result` is undefined.
Marko Mikulicic 0:c0ecb8bf28eb 4570 * - V7_EXEC_EXCEPTION if `js_code` threw an exception. `result` stores
Marko Mikulicic 0:c0ecb8bf28eb 4571 * an exception object.
Marko Mikulicic 0:c0ecb8bf28eb 4572 * - V7_AST_TOO_LARGE if `js_code` contains an AST segment longer than 16 bit.
Marko Mikulicic 0:c0ecb8bf28eb 4573 * `result` is undefined. To avoid this error, build V7 with V7_LARGE_AST.
Marko Mikulicic 0:c0ecb8bf28eb 4574 */
Marko Mikulicic 0:c0ecb8bf28eb 4575 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4576 enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *result);
Marko Mikulicic 0:c0ecb8bf28eb 4577
Marko Mikulicic 0:c0ecb8bf28eb 4578 /*
Marko Mikulicic 0:c0ecb8bf28eb 4579 * Options for `v7_exec_opt()`. To get default options, like `v7_exec()` uses,
Marko Mikulicic 0:c0ecb8bf28eb 4580 * just zero out this struct.
Marko Mikulicic 0:c0ecb8bf28eb 4581 */
Marko Mikulicic 0:c0ecb8bf28eb 4582 struct v7_exec_opts {
Marko Mikulicic 0:c0ecb8bf28eb 4583 /* Filename, used for stack traces only */
Marko Mikulicic 0:c0ecb8bf28eb 4584 const char *filename;
Marko Mikulicic 0:c0ecb8bf28eb 4585
Marko Mikulicic 0:c0ecb8bf28eb 4586 /*
Marko Mikulicic 0:c0ecb8bf28eb 4587 * Object to be used as `this`. Note: when it is zeroed out, i.e. it's a
Marko Mikulicic 0:c0ecb8bf28eb 4588 * number `0`, the `undefined` value is assumed. It means that it's
Marko Mikulicic 0:c0ecb8bf28eb 4589 * impossible to actually use the number `0` as `this` object, but it makes
Marko Mikulicic 0:c0ecb8bf28eb 4590 * little sense anyway.
Marko Mikulicic 0:c0ecb8bf28eb 4591 */
Marko Mikulicic 0:c0ecb8bf28eb 4592 v7_val_t this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 4593
Marko Mikulicic 0:c0ecb8bf28eb 4594 /* Whether the given `js_code` should be interpreted as JSON, not JS code */
Marko Mikulicic 0:c0ecb8bf28eb 4595 unsigned is_json : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4596 };
Marko Mikulicic 0:c0ecb8bf28eb 4597
Marko Mikulicic 0:c0ecb8bf28eb 4598 /*
Marko Mikulicic 0:c0ecb8bf28eb 4599 * Customizable version of `v7_exec()`: allows to specify various options, see
Marko Mikulicic 0:c0ecb8bf28eb 4600 * `struct v7_exec_opts`.
Marko Mikulicic 0:c0ecb8bf28eb 4601 */
Marko Mikulicic 0:c0ecb8bf28eb 4602 enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code,
Marko Mikulicic 0:c0ecb8bf28eb 4603 const struct v7_exec_opts *opts, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4604
Marko Mikulicic 0:c0ecb8bf28eb 4605 /*
Marko Mikulicic 0:c0ecb8bf28eb 4606 * Same as `v7_exec()`, but loads source code from `path` file.
Marko Mikulicic 0:c0ecb8bf28eb 4607 */
Marko Mikulicic 0:c0ecb8bf28eb 4608 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4609 enum v7_err v7_exec_file(struct v7 *v7, const char *path, v7_val_t *result);
Marko Mikulicic 0:c0ecb8bf28eb 4610
Marko Mikulicic 0:c0ecb8bf28eb 4611 /*
Marko Mikulicic 0:c0ecb8bf28eb 4612 * Parse `str` and store corresponding JavaScript object in `res` variable.
Marko Mikulicic 0:c0ecb8bf28eb 4613 * String `str` should be '\0'-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 4614 * Return value and semantic is the same as for `v7_exec()`.
Marko Mikulicic 0:c0ecb8bf28eb 4615 */
Marko Mikulicic 0:c0ecb8bf28eb 4616 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4617 enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4618
Marko Mikulicic 0:c0ecb8bf28eb 4619 /*
Marko Mikulicic 0:c0ecb8bf28eb 4620 * Same as `v7_parse_json()`, but loads JSON string from `path`.
Marko Mikulicic 0:c0ecb8bf28eb 4621 */
Marko Mikulicic 0:c0ecb8bf28eb 4622 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4623 enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4624
Marko Mikulicic 0:c0ecb8bf28eb 4625 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 4626
Marko Mikulicic 0:c0ecb8bf28eb 4627 /*
Marko Mikulicic 0:c0ecb8bf28eb 4628 * Compile JavaScript code `js_code` into the byte code and write generated
Marko Mikulicic 0:c0ecb8bf28eb 4629 * byte code into opened file stream `fp`. If `generate_binary_output` is 0,
Marko Mikulicic 0:c0ecb8bf28eb 4630 * then generated byte code is in human-readable text format. Otherwise, it is
Marko Mikulicic 0:c0ecb8bf28eb 4631 * in the binary format, suitable for execution by V7 instance.
Marko Mikulicic 0:c0ecb8bf28eb 4632 * NOTE: `fp` must be a valid, opened, writable file stream.
Marko Mikulicic 0:c0ecb8bf28eb 4633 */
Marko Mikulicic 0:c0ecb8bf28eb 4634 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4635 enum v7_err v7_compile(const char *js_code, int generate_binary_output,
Marko Mikulicic 0:c0ecb8bf28eb 4636 int use_bcode, FILE *fp);
Marko Mikulicic 0:c0ecb8bf28eb 4637
Marko Mikulicic 0:c0ecb8bf28eb 4638 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 4639
Marko Mikulicic 0:c0ecb8bf28eb 4640 /*
Marko Mikulicic 0:c0ecb8bf28eb 4641 * Call function `func` with arguments `args`, using `this_obj` as `this`.
Marko Mikulicic 0:c0ecb8bf28eb 4642 * `args` should be an array containing arguments or `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 4643 *
Marko Mikulicic 0:c0ecb8bf28eb 4644 * `res` can be `NULL` if return value is not required.
Marko Mikulicic 0:c0ecb8bf28eb 4645 */
Marko Mikulicic 0:c0ecb8bf28eb 4646 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4647 enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 4648 v7_val_t args, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4649
Marko Mikulicic 2:7762b98d31c7 4650 #if defined(__cplusplus)
Marko Mikulicic 2:7762b98d31c7 4651 }
Marko Mikulicic 2:7762b98d31c7 4652 #endif /* __cplusplus */
Marko Mikulicic 2:7762b98d31c7 4653
Marko Mikulicic 0:c0ecb8bf28eb 4654 #endif /* CS_V7_SRC_EXEC_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4655 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4656 #line 1 "v7/src/exec.h"
Marko Mikulicic 0:c0ecb8bf28eb 4657 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4658 /*
Marko Mikulicic 0:c0ecb8bf28eb 4659 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4660 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4661 */
Marko Mikulicic 0:c0ecb8bf28eb 4662
Marko Mikulicic 0:c0ecb8bf28eb 4663 #ifndef CS_V7_SRC_EXEC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4664 #define CS_V7_SRC_EXEC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4665
Marko Mikulicic 0:c0ecb8bf28eb 4666 /* Amalgamated: #include "v7/src/exec_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4667
Marko Mikulicic 0:c0ecb8bf28eb 4668 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4669
Marko Mikulicic 0:c0ecb8bf28eb 4670 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 4671
Marko Mikulicic 0:c0ecb8bf28eb 4672 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4673 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4674 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4675
Marko Mikulicic 0:c0ecb8bf28eb 4676 /*
Marko Mikulicic 0:c0ecb8bf28eb 4677 * At the moment, all exec-related functions are public, and are declared in
Marko Mikulicic 0:c0ecb8bf28eb 4678 * `exec_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 4679 */
Marko Mikulicic 0:c0ecb8bf28eb 4680
Marko Mikulicic 0:c0ecb8bf28eb 4681 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4682 enum v7_err _v7_compile(const char *js_code, size_t js_code_size,
Marko Mikulicic 0:c0ecb8bf28eb 4683 int generate_binary_output, int use_bcode, FILE *fp);
Marko Mikulicic 0:c0ecb8bf28eb 4684
Marko Mikulicic 0:c0ecb8bf28eb 4685 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4686 }
Marko Mikulicic 0:c0ecb8bf28eb 4687 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4688
Marko Mikulicic 0:c0ecb8bf28eb 4689 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 4690
Marko Mikulicic 0:c0ecb8bf28eb 4691 #endif /* CS_V7_SRC_EXEC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4692 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4693 #line 1 "v7/src/array_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4694 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4695 /*
Marko Mikulicic 0:c0ecb8bf28eb 4696 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4697 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4698 */
Marko Mikulicic 0:c0ecb8bf28eb 4699
Marko Mikulicic 0:c0ecb8bf28eb 4700 /*
Marko Mikulicic 0:c0ecb8bf28eb 4701 * === Arrays
Marko Mikulicic 0:c0ecb8bf28eb 4702 */
Marko Mikulicic 0:c0ecb8bf28eb 4703
Marko Mikulicic 0:c0ecb8bf28eb 4704 #ifndef CS_V7_SRC_ARRAY_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4705 #define CS_V7_SRC_ARRAY_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4706
Marko Mikulicic 0:c0ecb8bf28eb 4707 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4708
Marko Mikulicic 0:c0ecb8bf28eb 4709 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4710 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4711 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4712
Marko Mikulicic 0:c0ecb8bf28eb 4713 /* Make an empty array object */
Marko Mikulicic 0:c0ecb8bf28eb 4714 v7_val_t v7_mk_array(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4715
Marko Mikulicic 0:c0ecb8bf28eb 4716 /* Returns true if given value is an array object */
Marko Mikulicic 0:c0ecb8bf28eb 4717 int v7_is_array(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4718
Marko Mikulicic 0:c0ecb8bf28eb 4719 /* Returns length on an array. If `arr` is not an array, 0 is returned. */
Marko Mikulicic 0:c0ecb8bf28eb 4720 unsigned long v7_array_length(struct v7 *v7, v7_val_t arr);
Marko Mikulicic 0:c0ecb8bf28eb 4721
Marko Mikulicic 0:c0ecb8bf28eb 4722 /* Insert value `v` in array `arr` at the end of the array. */
Marko Mikulicic 0:c0ecb8bf28eb 4723 int v7_array_push(struct v7 *, v7_val_t arr, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4724
Marko Mikulicic 0:c0ecb8bf28eb 4725 /*
Marko Mikulicic 0:c0ecb8bf28eb 4726 * Like `v7_array_push()`, but "returns" value through the `res` pointer
Marko Mikulicic 0:c0ecb8bf28eb 4727 * argument. `res` is allowed to be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4728 *
Marko Mikulicic 0:c0ecb8bf28eb 4729 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 4730 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 4731 */
Marko Mikulicic 0:c0ecb8bf28eb 4732 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4733 enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v,
Marko Mikulicic 0:c0ecb8bf28eb 4734 int *res);
Marko Mikulicic 0:c0ecb8bf28eb 4735
Marko Mikulicic 0:c0ecb8bf28eb 4736 /*
Marko Mikulicic 0:c0ecb8bf28eb 4737 * Return array member at index `index`. If `index` is out of bounds, undefined
Marko Mikulicic 0:c0ecb8bf28eb 4738 * is returned.
Marko Mikulicic 0:c0ecb8bf28eb 4739 */
Marko Mikulicic 0:c0ecb8bf28eb 4740 v7_val_t v7_array_get(struct v7 *, v7_val_t arr, unsigned long index);
Marko Mikulicic 0:c0ecb8bf28eb 4741
Marko Mikulicic 0:c0ecb8bf28eb 4742 /* Insert value `v` into `arr` at index `index`. */
Marko Mikulicic 0:c0ecb8bf28eb 4743 int v7_array_set(struct v7 *v7, v7_val_t arr, unsigned long index, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4744
Marko Mikulicic 0:c0ecb8bf28eb 4745 /*
Marko Mikulicic 0:c0ecb8bf28eb 4746 * Like `v7_array_set()`, but "returns" value through the `res` pointer
Marko Mikulicic 0:c0ecb8bf28eb 4747 * argument. `res` is allowed to be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4748 *
Marko Mikulicic 0:c0ecb8bf28eb 4749 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 4750 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 4751 */
Marko Mikulicic 0:c0ecb8bf28eb 4752 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4753 enum v7_err v7_array_set_throwing(struct v7 *v7, v7_val_t arr,
Marko Mikulicic 0:c0ecb8bf28eb 4754 unsigned long index, v7_val_t v, int *res);
Marko Mikulicic 0:c0ecb8bf28eb 4755
Marko Mikulicic 0:c0ecb8bf28eb 4756 /* Delete value in array `arr` at index `index`, if it exists. */
Marko Mikulicic 0:c0ecb8bf28eb 4757 void v7_array_del(struct v7 *v7, v7_val_t arr, unsigned long index);
Marko Mikulicic 0:c0ecb8bf28eb 4758
Marko Mikulicic 0:c0ecb8bf28eb 4759 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4760 }
Marko Mikulicic 0:c0ecb8bf28eb 4761 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4762
Marko Mikulicic 0:c0ecb8bf28eb 4763 #endif /* CS_V7_SRC_ARRAY_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4764 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4765 #line 1 "v7/src/array.h"
Marko Mikulicic 0:c0ecb8bf28eb 4766 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4767 /*
Marko Mikulicic 0:c0ecb8bf28eb 4768 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4769 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4770 */
Marko Mikulicic 0:c0ecb8bf28eb 4771
Marko Mikulicic 0:c0ecb8bf28eb 4772 #ifndef CS_V7_SRC_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 4773 #define CS_V7_SRC_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 4774
Marko Mikulicic 0:c0ecb8bf28eb 4775 /* Amalgamated: #include "v7/src/array_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4776
Marko Mikulicic 0:c0ecb8bf28eb 4777 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4778
Marko Mikulicic 0:c0ecb8bf28eb 4779 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4780 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4781 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4782
Marko Mikulicic 0:c0ecb8bf28eb 4783 V7_PRIVATE v7_val_t v7_mk_dense_array(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4784 V7_PRIVATE val_t
Marko Mikulicic 0:c0ecb8bf28eb 4785 v7_array_get2(struct v7 *v7, v7_val_t arr, unsigned long index, int *has);
Marko Mikulicic 0:c0ecb8bf28eb 4786
Marko Mikulicic 0:c0ecb8bf28eb 4787 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4788 }
Marko Mikulicic 0:c0ecb8bf28eb 4789 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4790
Marko Mikulicic 0:c0ecb8bf28eb 4791 #endif /* CS_V7_SRC_ARRAY_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4792 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4793 #line 1 "v7/src/conversion_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4794 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4795 /*
Marko Mikulicic 0:c0ecb8bf28eb 4796 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4797 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4798 */
Marko Mikulicic 0:c0ecb8bf28eb 4799
Marko Mikulicic 0:c0ecb8bf28eb 4800 /*
Marko Mikulicic 0:c0ecb8bf28eb 4801 * === Conversion
Marko Mikulicic 0:c0ecb8bf28eb 4802 */
Marko Mikulicic 0:c0ecb8bf28eb 4803
Marko Mikulicic 0:c0ecb8bf28eb 4804 #ifndef CS_V7_SRC_CONVERSION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4805 #define CS_V7_SRC_CONVERSION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4806
Marko Mikulicic 0:c0ecb8bf28eb 4807 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4808
Marko Mikulicic 0:c0ecb8bf28eb 4809 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4810 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4811 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4812
Marko Mikulicic 0:c0ecb8bf28eb 4813 /* Stringify mode, see `v7_stringify()` and `v7_stringify_throwing()` */
Marko Mikulicic 0:c0ecb8bf28eb 4814 enum v7_stringify_mode {
Marko Mikulicic 0:c0ecb8bf28eb 4815 V7_STRINGIFY_DEFAULT,
Marko Mikulicic 0:c0ecb8bf28eb 4816 V7_STRINGIFY_JSON,
Marko Mikulicic 0:c0ecb8bf28eb 4817 V7_STRINGIFY_DEBUG,
Marko Mikulicic 0:c0ecb8bf28eb 4818 };
Marko Mikulicic 0:c0ecb8bf28eb 4819
Marko Mikulicic 0:c0ecb8bf28eb 4820 /*
Marko Mikulicic 0:c0ecb8bf28eb 4821 * Generate string representation of the JavaScript value `val` into a buffer
Marko Mikulicic 0:c0ecb8bf28eb 4822 * `buf`, `len`. If `len` is too small to hold a generated string,
Marko Mikulicic 0:c0ecb8bf28eb 4823 * `v7_stringify()` allocates required memory. In that case, it is caller's
Marko Mikulicic 0:c0ecb8bf28eb 4824 * responsibility to free the allocated buffer. Generated string is guaranteed
Marko Mikulicic 0:c0ecb8bf28eb 4825 * to be 0-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 4826 *
Marko Mikulicic 0:c0ecb8bf28eb 4827 * Available stringification modes are:
Marko Mikulicic 0:c0ecb8bf28eb 4828 *
Marko Mikulicic 0:c0ecb8bf28eb 4829 * - `V7_STRINGIFY_DEFAULT`:
Marko Mikulicic 0:c0ecb8bf28eb 4830 * Convert JS value to string, using common JavaScript semantics:
Marko Mikulicic 0:c0ecb8bf28eb 4831 * - If value is an object:
Marko Mikulicic 0:c0ecb8bf28eb 4832 * - call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 4833 * - If `toString()` returned non-primitive value, call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 4834 * - If `valueOf()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 4835 * - Now we have a primitive, and if it's not a string, then stringify it.
Marko Mikulicic 0:c0ecb8bf28eb 4836 *
Marko Mikulicic 0:c0ecb8bf28eb 4837 * - `V7_STRINGIFY_JSON`:
Marko Mikulicic 0:c0ecb8bf28eb 4838 * Generate JSON output
Marko Mikulicic 0:c0ecb8bf28eb 4839 *
Marko Mikulicic 0:c0ecb8bf28eb 4840 * - `V7_STRINGIFY_DEBUG`:
Marko Mikulicic 0:c0ecb8bf28eb 4841 * Mostly like JSON, but will not omit non-JSON objects like functions.
Marko Mikulicic 0:c0ecb8bf28eb 4842 *
Marko Mikulicic 0:c0ecb8bf28eb 4843 * Example code:
Marko Mikulicic 0:c0ecb8bf28eb 4844 *
Marko Mikulicic 0:c0ecb8bf28eb 4845 * char buf[100], *p;
Marko Mikulicic 0:c0ecb8bf28eb 4846 * p = v7_stringify(v7, obj, buf, sizeof(buf), V7_STRINGIFY_DEFAULT);
Marko Mikulicic 0:c0ecb8bf28eb 4847 * printf("JSON string: [%s]\n", p);
Marko Mikulicic 0:c0ecb8bf28eb 4848 * if (p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 4849 * free(p);
Marko Mikulicic 0:c0ecb8bf28eb 4850 * }
Marko Mikulicic 0:c0ecb8bf28eb 4851 */
Marko Mikulicic 0:c0ecb8bf28eb 4852 char *v7_stringify(struct v7 *v7, v7_val_t v, char *buf, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 4853 enum v7_stringify_mode mode);
Marko Mikulicic 0:c0ecb8bf28eb 4854
Marko Mikulicic 0:c0ecb8bf28eb 4855 /*
Marko Mikulicic 0:c0ecb8bf28eb 4856 * Like `v7_stringify()`, but "returns" value through the `res` pointer
Marko Mikulicic 0:c0ecb8bf28eb 4857 * argument. `res` must not be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4858 *
Marko Mikulicic 0:c0ecb8bf28eb 4859 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 4860 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 4861 */
Marko Mikulicic 0:c0ecb8bf28eb 4862 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4863 enum v7_err v7_stringify_throwing(struct v7 *v7, v7_val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 4864 size_t size, enum v7_stringify_mode mode,
Marko Mikulicic 0:c0ecb8bf28eb 4865 char **res);
Marko Mikulicic 0:c0ecb8bf28eb 4866
Marko Mikulicic 0:c0ecb8bf28eb 4867 /*
Marko Mikulicic 0:c0ecb8bf28eb 4868 * A shortcut for `v7_stringify()` with `V7_STRINGIFY_JSON`
Marko Mikulicic 0:c0ecb8bf28eb 4869 */
Marko Mikulicic 0:c0ecb8bf28eb 4870 #define v7_to_json(a, b, c, d) v7_stringify(a, b, c, d, V7_STRINGIFY_JSON)
Marko Mikulicic 0:c0ecb8bf28eb 4871
Marko Mikulicic 0:c0ecb8bf28eb 4872 /* Returns true if given value evaluates to true, as in `if (v)` statement. */
Marko Mikulicic 0:c0ecb8bf28eb 4873 int v7_is_truthy(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4874
Marko Mikulicic 0:c0ecb8bf28eb 4875 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4876 }
Marko Mikulicic 0:c0ecb8bf28eb 4877 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4878
Marko Mikulicic 0:c0ecb8bf28eb 4879 #endif /* CS_V7_SRC_CONVERSION_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4880 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4881 #line 1 "v7/src/conversion.h"
Marko Mikulicic 0:c0ecb8bf28eb 4882 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4883 /*
Marko Mikulicic 0:c0ecb8bf28eb 4884 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4885 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4886 */
Marko Mikulicic 0:c0ecb8bf28eb 4887
Marko Mikulicic 0:c0ecb8bf28eb 4888 #ifndef CS_V7_SRC_CONVERSION_H_
Marko Mikulicic 0:c0ecb8bf28eb 4889 #define CS_V7_SRC_CONVERSION_H_
Marko Mikulicic 0:c0ecb8bf28eb 4890
Marko Mikulicic 0:c0ecb8bf28eb 4891 /* Amalgamated: #include "v7/src/conversion_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4892
Marko Mikulicic 0:c0ecb8bf28eb 4893 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4894
Marko Mikulicic 0:c0ecb8bf28eb 4895 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4896 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4897 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4898
Marko Mikulicic 0:c0ecb8bf28eb 4899 /*
Marko Mikulicic 0:c0ecb8bf28eb 4900 * Conversion API
Marko Mikulicic 0:c0ecb8bf28eb 4901 * ==============
Marko Mikulicic 0:c0ecb8bf28eb 4902 *
Marko Mikulicic 0:c0ecb8bf28eb 4903 * - If you need to convert any JS value to string using common JavaScript
Marko Mikulicic 0:c0ecb8bf28eb 4904 * semantics, use `to_string()`, which can convert to both `v7_val_t` or your
Marko Mikulicic 0:c0ecb8bf28eb 4905 * C buffer.
Marko Mikulicic 0:c0ecb8bf28eb 4906 *
Marko Mikulicic 0:c0ecb8bf28eb 4907 * - If you need to convert any JS value to number using common JavaScript
Marko Mikulicic 0:c0ecb8bf28eb 4908 * semantics, use `to_number_v()`;
Marko Mikulicic 0:c0ecb8bf28eb 4909 *
Marko Mikulicic 0:c0ecb8bf28eb 4910 * - If you need to convert any JS value to primitive, without forcing it to
Marko Mikulicic 0:c0ecb8bf28eb 4911 * string or number, use `to_primitive()` (see comments for this function for
Marko Mikulicic 0:c0ecb8bf28eb 4912 * details);
Marko Mikulicic 0:c0ecb8bf28eb 4913 *
Marko Mikulicic 0:c0ecb8bf28eb 4914 * - If you have a primitive value, and you want to convert it to either string
Marko Mikulicic 0:c0ecb8bf28eb 4915 * or number, you can still use functions above: `to_string()` and
Marko Mikulicic 0:c0ecb8bf28eb 4916 * `to_number_v()`. But if you want to save a bit of work, use:
Marko Mikulicic 0:c0ecb8bf28eb 4917 * - `primitive_to_str()`
Marko Mikulicic 0:c0ecb8bf28eb 4918 * - `primitive_to_number()`
Marko Mikulicic 0:c0ecb8bf28eb 4919 *
Marko Mikulicic 0:c0ecb8bf28eb 4920 * In fact, these are a bit lower level functions, which are used by
Marko Mikulicic 0:c0ecb8bf28eb 4921 * `to_string()` and `to_number_v()` after converting value to
Marko Mikulicic 0:c0ecb8bf28eb 4922 * primitive.
Marko Mikulicic 0:c0ecb8bf28eb 4923 *
Marko Mikulicic 0:c0ecb8bf28eb 4924 * - If you want to call `valueOf()` on the object, use `obj_value_of()`;
Marko Mikulicic 0:c0ecb8bf28eb 4925 * - If you want to call `toString()` on the object, use `obj_to_string()`;
Marko Mikulicic 0:c0ecb8bf28eb 4926 *
Marko Mikulicic 0:c0ecb8bf28eb 4927 * - If you need to convert any JS value to boolean using common JavaScript
Marko Mikulicic 0:c0ecb8bf28eb 4928 * semantics (as in the expression `if (v)` or `Boolean(v)`), use
Marko Mikulicic 0:c0ecb8bf28eb 4929 * `to_boolean_v()`.
Marko Mikulicic 0:c0ecb8bf28eb 4930 *
Marko Mikulicic 0:c0ecb8bf28eb 4931 * - If you want to get the JSON representation of a value, use
Marko Mikulicic 0:c0ecb8bf28eb 4932 * `to_json_or_debug()`, passing `0` as `is_debug` : writes data to your C
Marko Mikulicic 0:c0ecb8bf28eb 4933 * buffer;
Marko Mikulicic 0:c0ecb8bf28eb 4934 *
Marko Mikulicic 0:c0ecb8bf28eb 4935 * - There is one more kind of representation: `DEBUG`. It's very similar to
Marko Mikulicic 0:c0ecb8bf28eb 4936 * JSON, but it will not omit non-JSON values, such as functions. Again, use
Marko Mikulicic 0:c0ecb8bf28eb 4937 * `to_json_or_debug()`, but pass `1` as `is_debug` this time: writes data to
Marko Mikulicic 0:c0ecb8bf28eb 4938 * your C buffer;
Marko Mikulicic 0:c0ecb8bf28eb 4939 *
Marko Mikulicic 0:c0ecb8bf28eb 4940 * Additionally, for any kind of to-string conversion into C buffer, you can
Marko Mikulicic 0:c0ecb8bf28eb 4941 * use a convenience wrapper function (mostly for public API), which can
Marko Mikulicic 0:c0ecb8bf28eb 4942 * allocate the buffer for you:
Marko Mikulicic 0:c0ecb8bf28eb 4943 *
Marko Mikulicic 0:c0ecb8bf28eb 4944 * - `v7_stringify_throwing()`;
Marko Mikulicic 0:c0ecb8bf28eb 4945 * - `v7_stringify()` : the same as above, but doesn't throw.
Marko Mikulicic 0:c0ecb8bf28eb 4946 *
Marko Mikulicic 0:c0ecb8bf28eb 4947 * There are a couple of more specific conversions, which I'd like to probably
Marko Mikulicic 0:c0ecb8bf28eb 4948 * refactor or remove in the future:
Marko Mikulicic 0:c0ecb8bf28eb 4949 *
Marko Mikulicic 0:c0ecb8bf28eb 4950 * - `to_long()` : if given value is `undefined`, returns provided default
Marko Mikulicic 0:c0ecb8bf28eb 4951 * value; otherwise, converts value to number, and then truncates to `long`.
Marko Mikulicic 0:c0ecb8bf28eb 4952 * - `str_to_ulong()` : converts the value to string, and tries to parse it as
Marko Mikulicic 0:c0ecb8bf28eb 4953 * an integer. Use it if only you need strong conformity ov the value to an
Marko Mikulicic 0:c0ecb8bf28eb 4954 * integer (currently, it's used only when examining keys of array object)
Marko Mikulicic 0:c0ecb8bf28eb 4955 *
Marko Mikulicic 0:c0ecb8bf28eb 4956 * ----------------------------------------------------------------------------
Marko Mikulicic 0:c0ecb8bf28eb 4957 *
Marko Mikulicic 0:c0ecb8bf28eb 4958 * TODO(dfrank):
Marko Mikulicic 0:c0ecb8bf28eb 4959 * - Rename functions like `v7_get_double(v7, )`, `get_object_struct()` to
Marko Mikulicic 0:c0ecb8bf28eb 4960 *something
Marko Mikulicic 0:c0ecb8bf28eb 4961 * that will clearly identify that they convert to some C entity, not
Marko Mikulicic 0:c0ecb8bf28eb 4962 * `v7_val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4963 * - Maybe make `to_string()` private? But then, there will be no way
Marko Mikulicic 0:c0ecb8bf28eb 4964 * in public API to convert value to `v7_val_t` string, so, for now
Marko Mikulicic 0:c0ecb8bf28eb 4965 * it's here.
Marko Mikulicic 0:c0ecb8bf28eb 4966 * - When we agree on what goes to public API, and what does not, write
Marko Mikulicic 0:c0ecb8bf28eb 4967 * similar conversion guide for public API (in `conversion_public.h`)
Marko Mikulicic 0:c0ecb8bf28eb 4968 */
Marko Mikulicic 0:c0ecb8bf28eb 4969
Marko Mikulicic 0:c0ecb8bf28eb 4970 /*
Marko Mikulicic 0:c0ecb8bf28eb 4971 * Convert any JS value to number, using common JavaScript semantics:
Marko Mikulicic 0:c0ecb8bf28eb 4972 *
Marko Mikulicic 0:c0ecb8bf28eb 4973 * - If value is an object:
Marko Mikulicic 0:c0ecb8bf28eb 4974 * - call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 4975 * - If `valueOf()` returned non-primitive value, call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 4976 * - If `toString()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 4977 * - Now we have a primitive, and if it's not a number, then:
Marko Mikulicic 0:c0ecb8bf28eb 4978 * - If `undefined`, return `NaN`
Marko Mikulicic 0:c0ecb8bf28eb 4979 * - If `null`, return 0.0
Marko Mikulicic 0:c0ecb8bf28eb 4980 * - If boolean, return either 1 or 0
Marko Mikulicic 0:c0ecb8bf28eb 4981 * - If string, try to parse it.
Marko Mikulicic 0:c0ecb8bf28eb 4982 */
Marko Mikulicic 0:c0ecb8bf28eb 4983 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4984 V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, v7_val_t v, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4985
Marko Mikulicic 0:c0ecb8bf28eb 4986 /*
Marko Mikulicic 0:c0ecb8bf28eb 4987 * Convert any JS value to string, using common JavaScript semantics,
Marko Mikulicic 0:c0ecb8bf28eb 4988 * see `v7_stringify()` and `V7_STRINGIFY_DEFAULT`.
Marko Mikulicic 0:c0ecb8bf28eb 4989 *
Marko Mikulicic 0:c0ecb8bf28eb 4990 * This function can return multiple things:
Marko Mikulicic 0:c0ecb8bf28eb 4991 *
Marko Mikulicic 0:c0ecb8bf28eb 4992 * - String as a `v7_val_t` (if `res` is not `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 4993 * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not
Marko Mikulicic 0:c0ecb8bf28eb 4994 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 4995 * - Length of actual string, independently of `buf_size` (if `res_len` is not
Marko Mikulicic 0:c0ecb8bf28eb 4996 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 4997 *
Marko Mikulicic 0:c0ecb8bf28eb 4998 * The rationale of having multiple formats of returned value is the following:
Marko Mikulicic 0:c0ecb8bf28eb 4999 *
Marko Mikulicic 0:c0ecb8bf28eb 5000 * Initially, to-string conversion always returned `v7_val_t`. But it turned
Marko Mikulicic 0:c0ecb8bf28eb 5001 * out that there are situations where such an approach adds useless pressure
Marko Mikulicic 0:c0ecb8bf28eb 5002 * on GC: e.g. when converting `undefined` to string, and the caller actually
Marko Mikulicic 0:c0ecb8bf28eb 5003 * needs a C buffer, not a `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 5004 *
Marko Mikulicic 0:c0ecb8bf28eb 5005 * Always returning string through `buf`+`buf_size` is bad as well: if we
Marko Mikulicic 0:c0ecb8bf28eb 5006 * convert from object to string, and either `toString()` or `valueOf()`
Marko Mikulicic 0:c0ecb8bf28eb 5007 * returned string, then we'd have to get string data from it, write to buffer,
Marko Mikulicic 0:c0ecb8bf28eb 5008 * and if caller actually need `v7_val_t`, then it will have to create new
Marko Mikulicic 0:c0ecb8bf28eb 5009 * instance of the same string: again, useless GC pressure.
Marko Mikulicic 0:c0ecb8bf28eb 5010 *
Marko Mikulicic 0:c0ecb8bf28eb 5011 * So, we have to use the combined approach. This function will make minimal
Marko Mikulicic 0:c0ecb8bf28eb 5012 * work depending on give `res` and `buf`.
Marko Mikulicic 0:c0ecb8bf28eb 5013 */
Marko Mikulicic 0:c0ecb8bf28eb 5014 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5015 V7_PRIVATE enum v7_err to_string(struct v7 *v7, v7_val_t v, v7_val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 5016 char *buf, size_t buf_size, size_t *res_len);
Marko Mikulicic 0:c0ecb8bf28eb 5017
Marko Mikulicic 0:c0ecb8bf28eb 5018 /*
Marko Mikulicic 0:c0ecb8bf28eb 5019 * Convert value to primitive, if it's not already.
Marko Mikulicic 0:c0ecb8bf28eb 5020 *
Marko Mikulicic 0:c0ecb8bf28eb 5021 * For object-to-primitive conversion, each object in JavaScript has two
Marko Mikulicic 0:c0ecb8bf28eb 5022 * methods: `toString()` and `valueOf()`.
Marko Mikulicic 0:c0ecb8bf28eb 5023 *
Marko Mikulicic 0:c0ecb8bf28eb 5024 * When converting object to string, JavaScript does the following:
Marko Mikulicic 0:c0ecb8bf28eb 5025 * - call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 5026 * - If `toString()` returned non-primitive value, call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 5027 * - If `valueOf()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 5028 *
Marko Mikulicic 0:c0ecb8bf28eb 5029 * When converting object to number, JavaScript calls the same functions,
Marko Mikulicic 0:c0ecb8bf28eb 5030 * but in reverse:
Marko Mikulicic 0:c0ecb8bf28eb 5031 * - call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 5032 * - If `valueOf()` returned non-primitive value, call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 5033 * - If `toString()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 5034 *
Marko Mikulicic 0:c0ecb8bf28eb 5035 * This function `to_primitive()` performs either type of conversion,
Marko Mikulicic 0:c0ecb8bf28eb 5036 * depending on the `hint` argument (see `enum to_primitive_hint`).
Marko Mikulicic 0:c0ecb8bf28eb 5037 */
Marko Mikulicic 0:c0ecb8bf28eb 5038 enum to_primitive_hint {
Marko Mikulicic 0:c0ecb8bf28eb 5039 /* Call `valueOf()` first, then `toString()` if needed */
Marko Mikulicic 0:c0ecb8bf28eb 5040 V7_TO_PRIMITIVE_HINT_NUMBER,
Marko Mikulicic 0:c0ecb8bf28eb 5041
Marko Mikulicic 0:c0ecb8bf28eb 5042 /* Call `toString()` first, then `valueOf()` if needed */
Marko Mikulicic 0:c0ecb8bf28eb 5043 V7_TO_PRIMITIVE_HINT_STRING,
Marko Mikulicic 0:c0ecb8bf28eb 5044
Marko Mikulicic 0:c0ecb8bf28eb 5045 /* STRING for Date, NUMBER for everything else */
Marko Mikulicic 0:c0ecb8bf28eb 5046 V7_TO_PRIMITIVE_HINT_AUTO,
Marko Mikulicic 0:c0ecb8bf28eb 5047 };
Marko Mikulicic 0:c0ecb8bf28eb 5048 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5049 enum v7_err to_primitive(struct v7 *v7, v7_val_t v, enum to_primitive_hint hint,
Marko Mikulicic 0:c0ecb8bf28eb 5050 v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5051
Marko Mikulicic 0:c0ecb8bf28eb 5052 /*
Marko Mikulicic 0:c0ecb8bf28eb 5053 * Convert primitive value to string, using common JavaScript semantics. If
Marko Mikulicic 0:c0ecb8bf28eb 5054 * you need to convert any value to string (either object or primitive),
Marko Mikulicic 0:c0ecb8bf28eb 5055 * see `to_string()` or `v7_stringify_throwing()`.
Marko Mikulicic 0:c0ecb8bf28eb 5056 *
Marko Mikulicic 0:c0ecb8bf28eb 5057 * This function can return multiple things:
Marko Mikulicic 0:c0ecb8bf28eb 5058 *
Marko Mikulicic 0:c0ecb8bf28eb 5059 * - String as a `v7_val_t` (if `res` is not `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 5060 * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not
Marko Mikulicic 0:c0ecb8bf28eb 5061 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 5062 * - Length of actual string, independently of `buf_size` (if `res_len` is not
Marko Mikulicic 0:c0ecb8bf28eb 5063 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 5064 */
Marko Mikulicic 0:c0ecb8bf28eb 5065 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5066 V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 5067 char *buf, size_t buf_size,
Marko Mikulicic 0:c0ecb8bf28eb 5068 size_t *res_len);
Marko Mikulicic 0:c0ecb8bf28eb 5069
Marko Mikulicic 0:c0ecb8bf28eb 5070 /*
Marko Mikulicic 0:c0ecb8bf28eb 5071 * Convert primitive value to number, using common JavaScript semantics. If you
Marko Mikulicic 0:c0ecb8bf28eb 5072 * need to convert any value to number (either object or primitive), see
Marko Mikulicic 0:c0ecb8bf28eb 5073 * `to_number_v()`
Marko Mikulicic 0:c0ecb8bf28eb 5074 */
Marko Mikulicic 0:c0ecb8bf28eb 5075 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5076 V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5077
Marko Mikulicic 0:c0ecb8bf28eb 5078 /*
Marko Mikulicic 0:c0ecb8bf28eb 5079 * Convert value to JSON or "debug" representation, depending on whether
Marko Mikulicic 0:c0ecb8bf28eb 5080 * `is_debug` is non-zero. The "debug" is the same as JSON, but non-JSON values
Marko Mikulicic 0:c0ecb8bf28eb 5081 * (functions, `undefined`, etc) will not be omitted.
Marko Mikulicic 0:c0ecb8bf28eb 5082 *
Marko Mikulicic 0:c0ecb8bf28eb 5083 * See also `v7_stringify()`, `v7_stringify_throwing()`.
Marko Mikulicic 0:c0ecb8bf28eb 5084 */
Marko Mikulicic 0:c0ecb8bf28eb 5085 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5086 V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 5087 size_t size, size_t *res_len,
Marko Mikulicic 0:c0ecb8bf28eb 5088 uint8_t is_debug);
Marko Mikulicic 0:c0ecb8bf28eb 5089
Marko Mikulicic 0:c0ecb8bf28eb 5090 /*
Marko Mikulicic 0:c0ecb8bf28eb 5091 * Calls `valueOf()` on given object `v`
Marko Mikulicic 0:c0ecb8bf28eb 5092 */
Marko Mikulicic 0:c0ecb8bf28eb 5093 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5094 V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5095
Marko Mikulicic 0:c0ecb8bf28eb 5096 /*
Marko Mikulicic 0:c0ecb8bf28eb 5097 * Calls `toString()` on given object `v`
Marko Mikulicic 0:c0ecb8bf28eb 5098 */
Marko Mikulicic 0:c0ecb8bf28eb 5099 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5100 V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5101
Marko Mikulicic 0:c0ecb8bf28eb 5102 /*
Marko Mikulicic 0:c0ecb8bf28eb 5103 * If given value is `undefined`, returns `default_value`; otherwise,
Marko Mikulicic 0:c0ecb8bf28eb 5104 * converts value to number, and then truncates to `long`.
Marko Mikulicic 0:c0ecb8bf28eb 5105 */
Marko Mikulicic 0:c0ecb8bf28eb 5106 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5107 V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value,
Marko Mikulicic 0:c0ecb8bf28eb 5108 long *res);
Marko Mikulicic 0:c0ecb8bf28eb 5109
Marko Mikulicic 0:c0ecb8bf28eb 5110 /*
Marko Mikulicic 0:c0ecb8bf28eb 5111 * Converts value to boolean as in the expression `if (v)` or `Boolean(v)`.
Marko Mikulicic 0:c0ecb8bf28eb 5112 *
Marko Mikulicic 0:c0ecb8bf28eb 5113 * NOTE: it can't throw (even if the given value is an object with `valueOf()`
Marko Mikulicic 0:c0ecb8bf28eb 5114 * that throws), so it returns `val_t` directly.
Marko Mikulicic 0:c0ecb8bf28eb 5115 */
Marko Mikulicic 0:c0ecb8bf28eb 5116 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5117 V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 5118
Marko Mikulicic 0:c0ecb8bf28eb 5119 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5120 }
Marko Mikulicic 0:c0ecb8bf28eb 5121 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5122
Marko Mikulicic 0:c0ecb8bf28eb 5123 #endif /* CS_V7_SRC_CONVERSION_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5124 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5125 #line 1 "v7/src/varint.h"
Marko Mikulicic 0:c0ecb8bf28eb 5126 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5127 /*
Marko Mikulicic 0:c0ecb8bf28eb 5128 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5129 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5130 */
Marko Mikulicic 0:c0ecb8bf28eb 5131
Marko Mikulicic 0:c0ecb8bf28eb 5132 #ifndef CS_V7_SRC_VARINT_H_
Marko Mikulicic 0:c0ecb8bf28eb 5133 #define CS_V7_SRC_VARINT_H_
Marko Mikulicic 0:c0ecb8bf28eb 5134
Marko Mikulicic 0:c0ecb8bf28eb 5135 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5136
Marko Mikulicic 0:c0ecb8bf28eb 5137 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5138 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5139 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5140
Marko Mikulicic 0:c0ecb8bf28eb 5141 V7_PRIVATE int encode_varint(size_t len, unsigned char *p);
Marko Mikulicic 0:c0ecb8bf28eb 5142 V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen);
Marko Mikulicic 0:c0ecb8bf28eb 5143 V7_PRIVATE int calc_llen(size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 5144
Marko Mikulicic 0:c0ecb8bf28eb 5145 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5146 }
Marko Mikulicic 0:c0ecb8bf28eb 5147 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5148
Marko Mikulicic 0:c0ecb8bf28eb 5149 #endif /* CS_V7_SRC_VARINT_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5150 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5151 #line 1 "common/cs_strtod.h"
Marko Mikulicic 0:c0ecb8bf28eb 5152 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5153 /*
Marko Mikulicic 0:c0ecb8bf28eb 5154 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5155 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5156 */
Marko Mikulicic 0:c0ecb8bf28eb 5157
Marko Mikulicic 0:c0ecb8bf28eb 5158 #ifndef CS_COMMON_CS_STRTOD_H_
Marko Mikulicic 0:c0ecb8bf28eb 5159 #define CS_COMMON_CS_STRTOD_H_
Marko Mikulicic 0:c0ecb8bf28eb 5160
Marko Mikulicic 0:c0ecb8bf28eb 5161 double cs_strtod(const char *str, char **endptr);
Marko Mikulicic 0:c0ecb8bf28eb 5162
Marko Mikulicic 0:c0ecb8bf28eb 5163 #endif /* CS_COMMON_CS_STRTOD_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5164 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5165 #line 1 "v7/src/ast.h"
Marko Mikulicic 0:c0ecb8bf28eb 5166 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5167 /*
Marko Mikulicic 0:c0ecb8bf28eb 5168 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5169 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5170 */
Marko Mikulicic 0:c0ecb8bf28eb 5171
Marko Mikulicic 0:c0ecb8bf28eb 5172 #ifndef CS_V7_SRC_AST_H_
Marko Mikulicic 0:c0ecb8bf28eb 5173 #define CS_V7_SRC_AST_H_
Marko Mikulicic 0:c0ecb8bf28eb 5174
Marko Mikulicic 0:c0ecb8bf28eb 5175 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 5176 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5177 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5178 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5179
Marko Mikulicic 0:c0ecb8bf28eb 5180 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 5181
Marko Mikulicic 0:c0ecb8bf28eb 5182 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5183 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5184 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5185
Marko Mikulicic 0:c0ecb8bf28eb 5186 #define BIN_AST_SIGNATURE "V\007ASTV10"
Marko Mikulicic 0:c0ecb8bf28eb 5187
Marko Mikulicic 0:c0ecb8bf28eb 5188 enum ast_tag {
Marko Mikulicic 0:c0ecb8bf28eb 5189 AST_NOP,
Marko Mikulicic 0:c0ecb8bf28eb 5190 AST_SCRIPT,
Marko Mikulicic 0:c0ecb8bf28eb 5191 AST_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 5192 AST_VAR_DECL,
Marko Mikulicic 0:c0ecb8bf28eb 5193 AST_FUNC_DECL,
Marko Mikulicic 0:c0ecb8bf28eb 5194 AST_IF,
Marko Mikulicic 0:c0ecb8bf28eb 5195 AST_FUNC,
Marko Mikulicic 0:c0ecb8bf28eb 5196
Marko Mikulicic 0:c0ecb8bf28eb 5197 AST_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5198 AST_REM_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5199 AST_MUL_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5200 AST_DIV_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5201 AST_XOR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5202 AST_PLUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5203 AST_MINUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5204 AST_OR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5205 AST_AND_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5206 AST_LSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5207 AST_RSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5208 AST_URSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5209
Marko Mikulicic 0:c0ecb8bf28eb 5210 AST_NUM,
Marko Mikulicic 0:c0ecb8bf28eb 5211 AST_IDENT,
Marko Mikulicic 0:c0ecb8bf28eb 5212 AST_STRING,
Marko Mikulicic 0:c0ecb8bf28eb 5213 AST_REGEX,
Marko Mikulicic 0:c0ecb8bf28eb 5214 AST_LABEL,
Marko Mikulicic 0:c0ecb8bf28eb 5215
Marko Mikulicic 0:c0ecb8bf28eb 5216 AST_SEQ,
Marko Mikulicic 0:c0ecb8bf28eb 5217 AST_WHILE,
Marko Mikulicic 0:c0ecb8bf28eb 5218 AST_DOWHILE,
Marko Mikulicic 0:c0ecb8bf28eb 5219 AST_FOR,
Marko Mikulicic 0:c0ecb8bf28eb 5220 AST_FOR_IN,
Marko Mikulicic 0:c0ecb8bf28eb 5221 AST_COND,
Marko Mikulicic 0:c0ecb8bf28eb 5222
Marko Mikulicic 0:c0ecb8bf28eb 5223 AST_DEBUGGER,
Marko Mikulicic 0:c0ecb8bf28eb 5224 AST_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 5225 AST_LABELED_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 5226 AST_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 5227 AST_LABELED_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 5228 AST_RETURN,
Marko Mikulicic 0:c0ecb8bf28eb 5229 AST_VALUE_RETURN,
Marko Mikulicic 0:c0ecb8bf28eb 5230 AST_THROW,
Marko Mikulicic 0:c0ecb8bf28eb 5231
Marko Mikulicic 0:c0ecb8bf28eb 5232 AST_TRY,
Marko Mikulicic 0:c0ecb8bf28eb 5233 AST_SWITCH,
Marko Mikulicic 0:c0ecb8bf28eb 5234 AST_CASE,
Marko Mikulicic 0:c0ecb8bf28eb 5235 AST_DEFAULT,
Marko Mikulicic 0:c0ecb8bf28eb 5236 AST_WITH,
Marko Mikulicic 0:c0ecb8bf28eb 5237
Marko Mikulicic 0:c0ecb8bf28eb 5238 AST_LOGICAL_OR,
Marko Mikulicic 0:c0ecb8bf28eb 5239 AST_LOGICAL_AND,
Marko Mikulicic 0:c0ecb8bf28eb 5240 AST_OR,
Marko Mikulicic 0:c0ecb8bf28eb 5241 AST_XOR,
Marko Mikulicic 0:c0ecb8bf28eb 5242 AST_AND,
Marko Mikulicic 0:c0ecb8bf28eb 5243
Marko Mikulicic 0:c0ecb8bf28eb 5244 AST_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 5245 AST_EQ_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 5246 AST_NE,
Marko Mikulicic 0:c0ecb8bf28eb 5247 AST_NE_NE,
Marko Mikulicic 0:c0ecb8bf28eb 5248
Marko Mikulicic 0:c0ecb8bf28eb 5249 AST_LE,
Marko Mikulicic 0:c0ecb8bf28eb 5250 AST_LT,
Marko Mikulicic 0:c0ecb8bf28eb 5251 AST_GE,
Marko Mikulicic 0:c0ecb8bf28eb 5252 AST_GT,
Marko Mikulicic 0:c0ecb8bf28eb 5253 AST_IN,
Marko Mikulicic 0:c0ecb8bf28eb 5254 AST_INSTANCEOF,
Marko Mikulicic 0:c0ecb8bf28eb 5255
Marko Mikulicic 0:c0ecb8bf28eb 5256 AST_LSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 5257 AST_RSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 5258 AST_URSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 5259
Marko Mikulicic 0:c0ecb8bf28eb 5260 AST_ADD,
Marko Mikulicic 0:c0ecb8bf28eb 5261 AST_SUB,
Marko Mikulicic 0:c0ecb8bf28eb 5262
Marko Mikulicic 0:c0ecb8bf28eb 5263 AST_REM,
Marko Mikulicic 0:c0ecb8bf28eb 5264 AST_MUL,
Marko Mikulicic 0:c0ecb8bf28eb 5265 AST_DIV,
Marko Mikulicic 0:c0ecb8bf28eb 5266
Marko Mikulicic 0:c0ecb8bf28eb 5267 AST_POSITIVE,
Marko Mikulicic 0:c0ecb8bf28eb 5268 AST_NEGATIVE,
Marko Mikulicic 0:c0ecb8bf28eb 5269 AST_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 5270 AST_LOGICAL_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 5271 AST_VOID,
Marko Mikulicic 0:c0ecb8bf28eb 5272 AST_DELETE,
Marko Mikulicic 0:c0ecb8bf28eb 5273 AST_TYPEOF,
Marko Mikulicic 0:c0ecb8bf28eb 5274 AST_PREINC,
Marko Mikulicic 0:c0ecb8bf28eb 5275 AST_PREDEC,
Marko Mikulicic 0:c0ecb8bf28eb 5276
Marko Mikulicic 0:c0ecb8bf28eb 5277 AST_POSTINC,
Marko Mikulicic 0:c0ecb8bf28eb 5278 AST_POSTDEC,
Marko Mikulicic 0:c0ecb8bf28eb 5279
Marko Mikulicic 0:c0ecb8bf28eb 5280 AST_MEMBER,
Marko Mikulicic 0:c0ecb8bf28eb 5281 AST_INDEX,
Marko Mikulicic 0:c0ecb8bf28eb 5282 AST_CALL,
Marko Mikulicic 0:c0ecb8bf28eb 5283
Marko Mikulicic 0:c0ecb8bf28eb 5284 AST_NEW,
Marko Mikulicic 0:c0ecb8bf28eb 5285
Marko Mikulicic 0:c0ecb8bf28eb 5286 AST_ARRAY,
Marko Mikulicic 0:c0ecb8bf28eb 5287 AST_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 5288 AST_PROP,
Marko Mikulicic 0:c0ecb8bf28eb 5289 AST_GETTER,
Marko Mikulicic 0:c0ecb8bf28eb 5290 AST_SETTER,
Marko Mikulicic 0:c0ecb8bf28eb 5291
Marko Mikulicic 0:c0ecb8bf28eb 5292 AST_THIS,
Marko Mikulicic 0:c0ecb8bf28eb 5293 AST_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 5294 AST_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 5295 AST_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 5296 AST_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 5297
Marko Mikulicic 0:c0ecb8bf28eb 5298 AST_USE_STRICT,
Marko Mikulicic 0:c0ecb8bf28eb 5299
Marko Mikulicic 0:c0ecb8bf28eb 5300 AST_MAX_TAG
Marko Mikulicic 0:c0ecb8bf28eb 5301 };
Marko Mikulicic 0:c0ecb8bf28eb 5302
Marko Mikulicic 0:c0ecb8bf28eb 5303 struct ast {
Marko Mikulicic 0:c0ecb8bf28eb 5304 struct mbuf mbuf;
Marko Mikulicic 0:c0ecb8bf28eb 5305 int refcnt;
Marko Mikulicic 0:c0ecb8bf28eb 5306 int has_overflow;
Marko Mikulicic 0:c0ecb8bf28eb 5307 };
Marko Mikulicic 0:c0ecb8bf28eb 5308
Marko Mikulicic 0:c0ecb8bf28eb 5309 typedef unsigned long ast_off_t;
Marko Mikulicic 0:c0ecb8bf28eb 5310
Marko Mikulicic 0:c0ecb8bf28eb 5311 #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
Marko Mikulicic 0:c0ecb8bf28eb 5312 #define GCC_HAS_PRAGMA_DIAGNOSTIC
Marko Mikulicic 0:c0ecb8bf28eb 5313 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5314
Marko Mikulicic 0:c0ecb8bf28eb 5315 #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC
Marko Mikulicic 0:c0ecb8bf28eb 5316 /*
Marko Mikulicic 0:c0ecb8bf28eb 5317 * TODO(mkm): GCC complains that bitfields on char are not standard
Marko Mikulicic 0:c0ecb8bf28eb 5318 */
Marko Mikulicic 0:c0ecb8bf28eb 5319 #pragma GCC diagnostic push
Marko Mikulicic 0:c0ecb8bf28eb 5320 #pragma GCC diagnostic ignored "-Wpedantic"
Marko Mikulicic 0:c0ecb8bf28eb 5321 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5322 struct ast_node_def {
Marko Mikulicic 0:c0ecb8bf28eb 5323 #ifndef V7_DISABLE_AST_TAG_NAMES
Marko Mikulicic 0:c0ecb8bf28eb 5324 const char *name; /* tag name, for debugging and serialization */
Marko Mikulicic 0:c0ecb8bf28eb 5325 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5326 unsigned char has_varint : 1; /* has a varint body */
Marko Mikulicic 0:c0ecb8bf28eb 5327 unsigned char has_inlined : 1; /* inlined data whose size is in varint fld */
Marko Mikulicic 0:c0ecb8bf28eb 5328 unsigned char num_skips : 3; /* number of skips */
Marko Mikulicic 0:c0ecb8bf28eb 5329 unsigned char num_subtrees : 3; /* number of fixed subtrees */
Marko Mikulicic 0:c0ecb8bf28eb 5330 };
Marko Mikulicic 0:c0ecb8bf28eb 5331 extern const struct ast_node_def ast_node_defs[];
Marko Mikulicic 0:c0ecb8bf28eb 5332 #if V7_ENABLE_FOOTPRINT_REPORT
Marko Mikulicic 0:c0ecb8bf28eb 5333 extern const size_t ast_node_defs_size;
Marko Mikulicic 0:c0ecb8bf28eb 5334 extern const size_t ast_node_defs_count;
Marko Mikulicic 0:c0ecb8bf28eb 5335 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5336 #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC
Marko Mikulicic 0:c0ecb8bf28eb 5337 #pragma GCC diagnostic pop
Marko Mikulicic 0:c0ecb8bf28eb 5338 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5339
Marko Mikulicic 0:c0ecb8bf28eb 5340 enum ast_which_skip {
Marko Mikulicic 0:c0ecb8bf28eb 5341 AST_END_SKIP = 0,
Marko Mikulicic 0:c0ecb8bf28eb 5342 AST_VAR_NEXT_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5343 AST_SCRIPT_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP,
Marko Mikulicic 0:c0ecb8bf28eb 5344 AST_FOR_BODY_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5345 AST_DO_WHILE_COND_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5346 AST_END_IF_TRUE_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5347 AST_TRY_CATCH_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5348 AST_TRY_FINALLY_SKIP = 2,
Marko Mikulicic 0:c0ecb8bf28eb 5349 AST_FUNC_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP,
Marko Mikulicic 0:c0ecb8bf28eb 5350 AST_FUNC_BODY_SKIP = 2,
Marko Mikulicic 0:c0ecb8bf28eb 5351 AST_SWITCH_DEFAULT_SKIP = 1
Marko Mikulicic 0:c0ecb8bf28eb 5352 };
Marko Mikulicic 0:c0ecb8bf28eb 5353
Marko Mikulicic 0:c0ecb8bf28eb 5354 V7_PRIVATE void ast_init(struct ast *, size_t);
Marko Mikulicic 0:c0ecb8bf28eb 5355 V7_PRIVATE void ast_optimize(struct ast *);
Marko Mikulicic 0:c0ecb8bf28eb 5356 V7_PRIVATE void ast_free(struct ast *);
Marko Mikulicic 0:c0ecb8bf28eb 5357
Marko Mikulicic 0:c0ecb8bf28eb 5358 /*
Marko Mikulicic 0:c0ecb8bf28eb 5359 * Begins an AST node by inserting a tag to the AST at the given offset.
Marko Mikulicic 0:c0ecb8bf28eb 5360 *
Marko Mikulicic 0:c0ecb8bf28eb 5361 * It also allocates space for the fixed_size payload and the space for
Marko Mikulicic 0:c0ecb8bf28eb 5362 * the skips.
Marko Mikulicic 0:c0ecb8bf28eb 5363 *
Marko Mikulicic 0:c0ecb8bf28eb 5364 * The caller is responsible for appending children.
Marko Mikulicic 0:c0ecb8bf28eb 5365 *
Marko Mikulicic 0:c0ecb8bf28eb 5366 * Returns the offset of the node payload (one byte after the tag).
Marko Mikulicic 0:c0ecb8bf28eb 5367 * This offset can be passed to `ast_set_skip`.
Marko Mikulicic 0:c0ecb8bf28eb 5368 */
Marko Mikulicic 0:c0ecb8bf28eb 5369 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 5370 ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag);
Marko Mikulicic 0:c0ecb8bf28eb 5371
Marko Mikulicic 0:c0ecb8bf28eb 5372 /*
Marko Mikulicic 0:c0ecb8bf28eb 5373 * Modify tag which is already added to buffer. Keeps `AST_TAG_LINENO_PRESENT`
Marko Mikulicic 0:c0ecb8bf28eb 5374 * flag.
Marko Mikulicic 0:c0ecb8bf28eb 5375 */
Marko Mikulicic 0:c0ecb8bf28eb 5376 V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off,
Marko Mikulicic 0:c0ecb8bf28eb 5377 enum ast_tag tag);
Marko Mikulicic 0:c0ecb8bf28eb 5378
Marko Mikulicic 0:c0ecb8bf28eb 5379 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 5380 /*
Marko Mikulicic 0:c0ecb8bf28eb 5381 * Add line_no varint after all skips of the tag at the offset `tag_off`, and
Marko Mikulicic 0:c0ecb8bf28eb 5382 * marks the tag byte.
Marko Mikulicic 0:c0ecb8bf28eb 5383 *
Marko Mikulicic 0:c0ecb8bf28eb 5384 * Byte at the offset `tag_off` should be a valid tag.
Marko Mikulicic 0:c0ecb8bf28eb 5385 */
Marko Mikulicic 0:c0ecb8bf28eb 5386 V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no);
Marko Mikulicic 0:c0ecb8bf28eb 5387 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5388
Marko Mikulicic 0:c0ecb8bf28eb 5389 /*
Marko Mikulicic 0:c0ecb8bf28eb 5390 * Patches a given skip slot for an already emitted node with the
Marko Mikulicic 0:c0ecb8bf28eb 5391 * current write cursor position (e.g. AST length).
Marko Mikulicic 0:c0ecb8bf28eb 5392 *
Marko Mikulicic 0:c0ecb8bf28eb 5393 * This is intended to be invoked when a node with a variable number
Marko Mikulicic 0:c0ecb8bf28eb 5394 * of child subtrees is closed, or when the consumers need a shortcut
Marko Mikulicic 0:c0ecb8bf28eb 5395 * to the next sibling.
Marko Mikulicic 0:c0ecb8bf28eb 5396 *
Marko Mikulicic 0:c0ecb8bf28eb 5397 * Each node type has a different number and semantic for skips,
Marko Mikulicic 0:c0ecb8bf28eb 5398 * all of them defined in the `ast_which_skip` enum.
Marko Mikulicic 0:c0ecb8bf28eb 5399 * All nodes having a variable number of child subtrees must define
Marko Mikulicic 0:c0ecb8bf28eb 5400 * at least the `AST_END_SKIP` skip, which effectively skips a node
Marko Mikulicic 0:c0ecb8bf28eb 5401 * boundary.
Marko Mikulicic 0:c0ecb8bf28eb 5402 *
Marko Mikulicic 0:c0ecb8bf28eb 5403 * Every tree reader can assume this and safely skip unknown nodes.
Marko Mikulicic 0:c0ecb8bf28eb 5404 *
Marko Mikulicic 0:c0ecb8bf28eb 5405 * `pos` should be an offset of the byte right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5406 */
Marko Mikulicic 0:c0ecb8bf28eb 5407 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 5408 ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip);
Marko Mikulicic 0:c0ecb8bf28eb 5409
Marko Mikulicic 0:c0ecb8bf28eb 5410 /*
Marko Mikulicic 0:c0ecb8bf28eb 5411 * Patches a given skip slot for an already emitted node with the value
Marko Mikulicic 0:c0ecb8bf28eb 5412 * (stored as delta relative to the `pos` node) of the `where` argument.
Marko Mikulicic 0:c0ecb8bf28eb 5413 */
Marko Mikulicic 0:c0ecb8bf28eb 5414 V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 5415 ast_off_t where, enum ast_which_skip skip);
Marko Mikulicic 0:c0ecb8bf28eb 5416
Marko Mikulicic 0:c0ecb8bf28eb 5417 /*
Marko Mikulicic 0:c0ecb8bf28eb 5418 * Returns the offset in AST to which the given `skip` points.
Marko Mikulicic 0:c0ecb8bf28eb 5419 *
Marko Mikulicic 0:c0ecb8bf28eb 5420 * `pos` should be an offset of the byte right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5421 */
Marko Mikulicic 0:c0ecb8bf28eb 5422 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 5423 ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip);
Marko Mikulicic 0:c0ecb8bf28eb 5424
Marko Mikulicic 0:c0ecb8bf28eb 5425 /*
Marko Mikulicic 0:c0ecb8bf28eb 5426 * Returns the tag from the offset `ppos`, and shifts `ppos` by 1.
Marko Mikulicic 0:c0ecb8bf28eb 5427 */
Marko Mikulicic 0:c0ecb8bf28eb 5428 V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5429
Marko Mikulicic 0:c0ecb8bf28eb 5430 /*
Marko Mikulicic 0:c0ecb8bf28eb 5431 * Moves the cursor to the tag's varint and inlined data (if there are any, see
Marko Mikulicic 0:c0ecb8bf28eb 5432 * `struct ast_node_def::has_varint` and `struct ast_node_def::has_inlined`).
Marko Mikulicic 0:c0ecb8bf28eb 5433 *
Marko Mikulicic 0:c0ecb8bf28eb 5434 * Technically, it skips node's "skips" and line number data, if either is
Marko Mikulicic 0:c0ecb8bf28eb 5435 * present.
Marko Mikulicic 0:c0ecb8bf28eb 5436 *
Marko Mikulicic 0:c0ecb8bf28eb 5437 * Assumes a cursor (`ppos`) positioned right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5438 */
Marko Mikulicic 0:c0ecb8bf28eb 5439 V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5440
Marko Mikulicic 0:c0ecb8bf28eb 5441 /*
Marko Mikulicic 0:c0ecb8bf28eb 5442 * Moves the cursor to the tag's subtrees (if there are any,
Marko Mikulicic 0:c0ecb8bf28eb 5443 * see `struct ast_node_def::num_subtrees`), or to the next node in case the
Marko Mikulicic 0:c0ecb8bf28eb 5444 * current node has no subtrees.
Marko Mikulicic 0:c0ecb8bf28eb 5445 *
Marko Mikulicic 0:c0ecb8bf28eb 5446 * Technically, it skips node's "skips", line number data, and inlined data, if
Marko Mikulicic 0:c0ecb8bf28eb 5447 * either is present.
Marko Mikulicic 0:c0ecb8bf28eb 5448 *
Marko Mikulicic 0:c0ecb8bf28eb 5449 * Assumes a cursor (`ppos`) positioned right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5450 */
Marko Mikulicic 0:c0ecb8bf28eb 5451 V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5452
Marko Mikulicic 0:c0ecb8bf28eb 5453 /* Helper to add a node with inlined data. */
Marko Mikulicic 0:c0ecb8bf28eb 5454 V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 5455 enum ast_tag tag, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 5456 size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 5457
Marko Mikulicic 0:c0ecb8bf28eb 5458 /*
Marko Mikulicic 0:c0ecb8bf28eb 5459 * Returns the line number encoded in the node, or `0` in case of none is
Marko Mikulicic 0:c0ecb8bf28eb 5460 * encoded.
Marko Mikulicic 0:c0ecb8bf28eb 5461 *
Marko Mikulicic 0:c0ecb8bf28eb 5462 * `pos` should be an offset of the byte right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5463 */
Marko Mikulicic 0:c0ecb8bf28eb 5464 V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos);
Marko Mikulicic 0:c0ecb8bf28eb 5465
Marko Mikulicic 0:c0ecb8bf28eb 5466 /*
Marko Mikulicic 0:c0ecb8bf28eb 5467 * `pos` should be an offset of the byte right after a tag
Marko Mikulicic 0:c0ecb8bf28eb 5468 */
Marko Mikulicic 0:c0ecb8bf28eb 5469 V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n);
Marko Mikulicic 0:c0ecb8bf28eb 5470
Marko Mikulicic 0:c0ecb8bf28eb 5471 /*
Marko Mikulicic 0:c0ecb8bf28eb 5472 * Returns the `double` number inlined in the node
Marko Mikulicic 0:c0ecb8bf28eb 5473 */
Marko Mikulicic 0:c0ecb8bf28eb 5474 V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos);
Marko Mikulicic 0:c0ecb8bf28eb 5475
Marko Mikulicic 0:c0ecb8bf28eb 5476 /*
Marko Mikulicic 0:c0ecb8bf28eb 5477 * Skips the node and all its subnodes.
Marko Mikulicic 0:c0ecb8bf28eb 5478 *
Marko Mikulicic 0:c0ecb8bf28eb 5479 * Cursor (`ppos`) should be at the tag byte
Marko Mikulicic 0:c0ecb8bf28eb 5480 */
Marko Mikulicic 0:c0ecb8bf28eb 5481 V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5482
Marko Mikulicic 0:c0ecb8bf28eb 5483 V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 5484 int depth);
Marko Mikulicic 0:c0ecb8bf28eb 5485
Marko Mikulicic 0:c0ecb8bf28eb 5486 V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a);
Marko Mikulicic 0:c0ecb8bf28eb 5487
Marko Mikulicic 0:c0ecb8bf28eb 5488 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5489 }
Marko Mikulicic 0:c0ecb8bf28eb 5490 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5491
Marko Mikulicic 0:c0ecb8bf28eb 5492 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 5493
Marko Mikulicic 0:c0ecb8bf28eb 5494 #endif /* CS_V7_SRC_AST_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5495 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5496 #line 1 "v7/src/bcode.h"
Marko Mikulicic 0:c0ecb8bf28eb 5497 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5498 /*
Marko Mikulicic 0:c0ecb8bf28eb 5499 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5500 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5501 */
Marko Mikulicic 0:c0ecb8bf28eb 5502
Marko Mikulicic 0:c0ecb8bf28eb 5503 #ifndef CS_V7_SRC_BCODE_H_
Marko Mikulicic 0:c0ecb8bf28eb 5504 #define CS_V7_SRC_BCODE_H_
Marko Mikulicic 0:c0ecb8bf28eb 5505
Marko Mikulicic 0:c0ecb8bf28eb 5506 #define BIN_BCODE_SIGNATURE "V\007BCODE:"
Marko Mikulicic 0:c0ecb8bf28eb 5507
Marko Mikulicic 0:c0ecb8bf28eb 5508 #if !defined(V7_NAMES_CNT_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 5509 #define V7_NAMES_CNT_WIDTH 10
Marko Mikulicic 0:c0ecb8bf28eb 5510 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5511
Marko Mikulicic 0:c0ecb8bf28eb 5512 #if !defined(V7_ARGS_CNT_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 5513 #define V7_ARGS_CNT_WIDTH 8
Marko Mikulicic 0:c0ecb8bf28eb 5514 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5515
Marko Mikulicic 0:c0ecb8bf28eb 5516 #define V7_NAMES_CNT_MAX ((1 << V7_NAMES_CNT_WIDTH) - 1)
Marko Mikulicic 0:c0ecb8bf28eb 5517 #define V7_ARGS_CNT_MAX ((1 << V7_ARGS_CNT_WIDTH) - 1)
Marko Mikulicic 0:c0ecb8bf28eb 5518
Marko Mikulicic 0:c0ecb8bf28eb 5519 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5520 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5521 /* Amalgamated: #include "v7/src/opcodes.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5522 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5523 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5524 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5525 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5526
Marko Mikulicic 0:c0ecb8bf28eb 5527 enum bcode_inline_lit_type_tag {
Marko Mikulicic 0:c0ecb8bf28eb 5528 BCODE_INLINE_STRING_TYPE_TAG = 0,
Marko Mikulicic 0:c0ecb8bf28eb 5529 BCODE_INLINE_NUMBER_TYPE_TAG,
Marko Mikulicic 0:c0ecb8bf28eb 5530 BCODE_INLINE_FUNC_TYPE_TAG,
Marko Mikulicic 0:c0ecb8bf28eb 5531 BCODE_INLINE_REGEXP_TYPE_TAG,
Marko Mikulicic 0:c0ecb8bf28eb 5532
Marko Mikulicic 0:c0ecb8bf28eb 5533 BCODE_MAX_INLINE_TYPE_TAG
Marko Mikulicic 0:c0ecb8bf28eb 5534 };
Marko Mikulicic 0:c0ecb8bf28eb 5535
Marko Mikulicic 0:c0ecb8bf28eb 5536 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5537 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5538 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5539
Marko Mikulicic 0:c0ecb8bf28eb 5540 typedef uint32_t bcode_off_t;
Marko Mikulicic 0:c0ecb8bf28eb 5541
Marko Mikulicic 0:c0ecb8bf28eb 5542 /*
Marko Mikulicic 0:c0ecb8bf28eb 5543 * Each JS function will have one bcode structure
Marko Mikulicic 0:c0ecb8bf28eb 5544 * containing the instruction stream, a literal table, and function
Marko Mikulicic 0:c0ecb8bf28eb 5545 * metadata.
Marko Mikulicic 0:c0ecb8bf28eb 5546 * Instructions contain references to literals (strings, constants, etc)
Marko Mikulicic 0:c0ecb8bf28eb 5547 *
Marko Mikulicic 0:c0ecb8bf28eb 5548 * The bcode struct can be shared between function instances
Marko Mikulicic 0:c0ecb8bf28eb 5549 * and keeps a reference count used to free it in the function destructor.
Marko Mikulicic 0:c0ecb8bf28eb 5550 */
Marko Mikulicic 0:c0ecb8bf28eb 5551 struct bcode {
Marko Mikulicic 0:c0ecb8bf28eb 5552 /*
Marko Mikulicic 0:c0ecb8bf28eb 5553 * Names + instruction opcode.
Marko Mikulicic 0:c0ecb8bf28eb 5554 * Names are null-terminates strings. For function's bcode, there are:
Marko Mikulicic 0:c0ecb8bf28eb 5555 * - function name (for anonymous function, the name is still present: an
Marko Mikulicic 0:c0ecb8bf28eb 5556 * empty string);
Marko Mikulicic 0:c0ecb8bf28eb 5557 * - arg names (a number of args is determined by `args_cnt`, see below);
Marko Mikulicic 0:c0ecb8bf28eb 5558 * - local names (a number or locals can be calculated:
Marko Mikulicic 0:c0ecb8bf28eb 5559 * `(names_cnt - args_cnt - 1)`).
Marko Mikulicic 0:c0ecb8bf28eb 5560 *
Marko Mikulicic 0:c0ecb8bf28eb 5561 * For script's bcode, there are just local names.
Marko Mikulicic 0:c0ecb8bf28eb 5562 */
Marko Mikulicic 0:c0ecb8bf28eb 5563 struct v7_vec ops;
Marko Mikulicic 0:c0ecb8bf28eb 5564
Marko Mikulicic 0:c0ecb8bf28eb 5565 /* Literal table */
Marko Mikulicic 0:c0ecb8bf28eb 5566 struct v7_vec lit;
Marko Mikulicic 0:c0ecb8bf28eb 5567
Marko Mikulicic 0:c0ecb8bf28eb 5568 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 5569 /* Name of the file from which this bcode was generated (used for debug) */
Marko Mikulicic 0:c0ecb8bf28eb 5570 void *filename;
Marko Mikulicic 0:c0ecb8bf28eb 5571 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5572
Marko Mikulicic 0:c0ecb8bf28eb 5573 /* Reference count */
Marko Mikulicic 0:c0ecb8bf28eb 5574 uint8_t refcnt;
Marko Mikulicic 0:c0ecb8bf28eb 5575
Marko Mikulicic 0:c0ecb8bf28eb 5576 /* Total number of null-terminated strings in the beginning of `ops` */
Marko Mikulicic 0:c0ecb8bf28eb 5577 unsigned int names_cnt : V7_NAMES_CNT_WIDTH;
Marko Mikulicic 0:c0ecb8bf28eb 5578
Marko Mikulicic 0:c0ecb8bf28eb 5579 /* Number of args (should be <= `(names_cnt + 1)`) */
Marko Mikulicic 0:c0ecb8bf28eb 5580 unsigned int args_cnt : V7_ARGS_CNT_WIDTH;
Marko Mikulicic 0:c0ecb8bf28eb 5581
Marko Mikulicic 0:c0ecb8bf28eb 5582 unsigned int strict_mode : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5583 /*
Marko Mikulicic 0:c0ecb8bf28eb 5584 * If true this structure lives on read only memory, either
Marko Mikulicic 0:c0ecb8bf28eb 5585 * mmapped or constant data section.
Marko Mikulicic 0:c0ecb8bf28eb 5586 */
Marko Mikulicic 0:c0ecb8bf28eb 5587 unsigned int frozen : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5588
Marko Mikulicic 0:c0ecb8bf28eb 5589 /* If set, `ops.buf` points to ROM, so we shouldn't free it */
Marko Mikulicic 0:c0ecb8bf28eb 5590 unsigned int ops_in_rom : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5591 /* Set for deserialized bcode. Used for metrics only */
Marko Mikulicic 0:c0ecb8bf28eb 5592 unsigned int deserialized : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5593
Marko Mikulicic 0:c0ecb8bf28eb 5594 /* Set when `ops` contains function name as the first `name` */
Marko Mikulicic 0:c0ecb8bf28eb 5595 unsigned int func_name_present : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5596
Marko Mikulicic 0:c0ecb8bf28eb 5597 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 5598 /* If set, `filename` points to ROM, so we shouldn't free it */
Marko Mikulicic 0:c0ecb8bf28eb 5599 unsigned int filename_in_rom : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5600 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5601 };
Marko Mikulicic 0:c0ecb8bf28eb 5602
Marko Mikulicic 0:c0ecb8bf28eb 5603 /*
Marko Mikulicic 0:c0ecb8bf28eb 5604 * Bcode builder context: it contains mutable mbufs for opcodes and literals,
Marko Mikulicic 0:c0ecb8bf28eb 5605 * whereas the bcode itself contains just vectors (`struct v7_vec`).
Marko Mikulicic 0:c0ecb8bf28eb 5606 */
Marko Mikulicic 0:c0ecb8bf28eb 5607 struct bcode_builder {
Marko Mikulicic 0:c0ecb8bf28eb 5608 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 5609 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 5610
Marko Mikulicic 0:c0ecb8bf28eb 5611 struct mbuf ops; /* names + instruction opcode */
Marko Mikulicic 0:c0ecb8bf28eb 5612 struct mbuf lit; /* literal table */
Marko Mikulicic 0:c0ecb8bf28eb 5613 };
Marko Mikulicic 0:c0ecb8bf28eb 5614
Marko Mikulicic 0:c0ecb8bf28eb 5615 V7_PRIVATE void bcode_builder_init(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 5616 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5617 struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5618 V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 5619
Marko Mikulicic 0:c0ecb8bf28eb 5620 /*
Marko Mikulicic 0:c0ecb8bf28eb 5621 * Note: `filename` must be either:
Marko Mikulicic 0:c0ecb8bf28eb 5622 *
Marko Mikulicic 0:c0ecb8bf28eb 5623 * - `NULL`. In this case, `filename_in_rom` is ignored.
Marko Mikulicic 0:c0ecb8bf28eb 5624 * - A pointer to ROM (or to any other unmanaged memory). `filename_in_rom`
Marko Mikulicic 0:c0ecb8bf28eb 5625 * must be set to 1.
Marko Mikulicic 0:c0ecb8bf28eb 5626 * - A pointer returned by `shdata_create()`, i.e. a pointer to shared data.
Marko Mikulicic 0:c0ecb8bf28eb 5627 *
Marko Mikulicic 0:c0ecb8bf28eb 5628 * If you need to copy filename from another bcode, just pass NULL initially,
Marko Mikulicic 0:c0ecb8bf28eb 5629 * and after bcode is initialized, call `bcode_copy_filename_from()`.
Marko Mikulicic 0:c0ecb8bf28eb 5630 *
Marko Mikulicic 0:c0ecb8bf28eb 5631 * To get later a proper null-terminated filename string from bcode, use
Marko Mikulicic 0:c0ecb8bf28eb 5632 * `bcode_get_filename()`.
Marko Mikulicic 0:c0ecb8bf28eb 5633 */
Marko Mikulicic 0:c0ecb8bf28eb 5634 V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode,
Marko Mikulicic 0:c0ecb8bf28eb 5635 void *filename, uint8_t filename_in_rom);
Marko Mikulicic 0:c0ecb8bf28eb 5636 V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5637 V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5638 V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5639
Marko Mikulicic 0:c0ecb8bf28eb 5640 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 5641 /*
Marko Mikulicic 0:c0ecb8bf28eb 5642 * Return a pointer to null-terminated filename string
Marko Mikulicic 0:c0ecb8bf28eb 5643 */
Marko Mikulicic 0:c0ecb8bf28eb 5644 V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5645 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5646
Marko Mikulicic 0:c0ecb8bf28eb 5647 /*
Marko Mikulicic 0:c0ecb8bf28eb 5648 * Copy filename from `src` to `dst`. If source filename is a pointer to ROM,
Marko Mikulicic 0:c0ecb8bf28eb 5649 * then just the pointer is copied; otherwise, appropriate shdata pointer is
Marko Mikulicic 0:c0ecb8bf28eb 5650 * retained.
Marko Mikulicic 0:c0ecb8bf28eb 5651 */
Marko Mikulicic 0:c0ecb8bf28eb 5652 V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src);
Marko Mikulicic 0:c0ecb8bf28eb 5653
Marko Mikulicic 0:c0ecb8bf28eb 5654 /*
Marko Mikulicic 0:c0ecb8bf28eb 5655 * Serialize a bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 5656 *
Marko Mikulicic 0:c0ecb8bf28eb 5657 * All literals, including functions, are inlined into `ops` data; see
Marko Mikulicic 0:c0ecb8bf28eb 5658 * the serialization logic in `bcode_op_lit()`.
Marko Mikulicic 0:c0ecb8bf28eb 5659 *
Marko Mikulicic 0:c0ecb8bf28eb 5660 * The root bcode looks just like a regular function.
Marko Mikulicic 0:c0ecb8bf28eb 5661 *
Marko Mikulicic 0:c0ecb8bf28eb 5662 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5663 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5664 */
Marko Mikulicic 0:c0ecb8bf28eb 5665 /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5666 FILE *f);
Marko Mikulicic 0:c0ecb8bf28eb 5667
Marko Mikulicic 0:c0ecb8bf28eb 5668 V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5669 const char *data);
Marko Mikulicic 0:c0ecb8bf28eb 5670
Marko Mikulicic 0:c0ecb8bf28eb 5671 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 5672 V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *, struct bcode *);
Marko Mikulicic 0:c0ecb8bf28eb 5673 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5674
Marko Mikulicic 0:c0ecb8bf28eb 5675 /* mode of literal storage: in literal table or inlined in `ops` */
Marko Mikulicic 0:c0ecb8bf28eb 5676 enum lit_mode {
Marko Mikulicic 0:c0ecb8bf28eb 5677 /* literal stored in table, index is in `lit_t::lit_idx` */
Marko Mikulicic 0:c0ecb8bf28eb 5678 LIT_MODE__TABLE,
Marko Mikulicic 0:c0ecb8bf28eb 5679 /* literal should be inlined in `ops`, value is in `lit_t::inline_val` */
Marko Mikulicic 0:c0ecb8bf28eb 5680 LIT_MODE__INLINED,
Marko Mikulicic 0:c0ecb8bf28eb 5681 };
Marko Mikulicic 0:c0ecb8bf28eb 5682
Marko Mikulicic 0:c0ecb8bf28eb 5683 /*
Marko Mikulicic 0:c0ecb8bf28eb 5684 * Result of the addition of literal value to bcode (see `bcode_add_lit()`).
Marko Mikulicic 0:c0ecb8bf28eb 5685 * There are two possible cases:
Marko Mikulicic 0:c0ecb8bf28eb 5686 *
Marko Mikulicic 0:c0ecb8bf28eb 5687 * - Literal is added to the literal table. In this case, `mode ==
Marko Mikulicic 0:c0ecb8bf28eb 5688 * LIT_MODE__TABLE`, and the index of the literal is stored in `lit_idx`
Marko Mikulicic 0:c0ecb8bf28eb 5689 * - Literal is not added anywhere, and should be inlined into `ops`. In this
Marko Mikulicic 0:c0ecb8bf28eb 5690 * case, `mode == LIT_MODE__INLINED`, and the value to inline is stored in
Marko Mikulicic 0:c0ecb8bf28eb 5691 * `inline_val`.
Marko Mikulicic 0:c0ecb8bf28eb 5692 *
Marko Mikulicic 0:c0ecb8bf28eb 5693 * It's `bcode_op_lit()` who handles both of these cases.
Marko Mikulicic 0:c0ecb8bf28eb 5694 */
Marko Mikulicic 0:c0ecb8bf28eb 5695 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 5696 union {
Marko Mikulicic 0:c0ecb8bf28eb 5697 /*
Marko Mikulicic 0:c0ecb8bf28eb 5698 * index in literal table;
Marko Mikulicic 0:c0ecb8bf28eb 5699 * NOTE: valid if only `mode == LIT_MODE__TABLE`
Marko Mikulicic 0:c0ecb8bf28eb 5700 */
Marko Mikulicic 0:c0ecb8bf28eb 5701 size_t lit_idx;
Marko Mikulicic 0:c0ecb8bf28eb 5702
Marko Mikulicic 0:c0ecb8bf28eb 5703 /*
Marko Mikulicic 0:c0ecb8bf28eb 5704 * value to be inlined into `ops`;
Marko Mikulicic 0:c0ecb8bf28eb 5705 * NOTE: valid if only `mode == LIT_MODE__INLINED`
Marko Mikulicic 0:c0ecb8bf28eb 5706 */
Marko Mikulicic 0:c0ecb8bf28eb 5707 v7_val_t inline_val;
Marko Mikulicic 0:c0ecb8bf28eb 5708 } v; /* anonymous unions are a c11 feature */
Marko Mikulicic 0:c0ecb8bf28eb 5709
Marko Mikulicic 0:c0ecb8bf28eb 5710 /*
Marko Mikulicic 0:c0ecb8bf28eb 5711 * mode of literal storage (see `enum lit_mode`)
Marko Mikulicic 0:c0ecb8bf28eb 5712 * NOTE: we need one more bit, because enum can be signed
Marko Mikulicic 0:c0ecb8bf28eb 5713 * on some compilers (e.g. msvc) and thus will get signextended
Marko Mikulicic 0:c0ecb8bf28eb 5714 * when moved to a `enum lit_mode` variable basically corrupting
Marko Mikulicic 0:c0ecb8bf28eb 5715 * the value. See https://github.com/cesanta/v7/issues/551
Marko Mikulicic 0:c0ecb8bf28eb 5716 */
Marko Mikulicic 0:c0ecb8bf28eb 5717 enum lit_mode mode : 2;
Marko Mikulicic 0:c0ecb8bf28eb 5718 } lit_t;
Marko Mikulicic 0:c0ecb8bf28eb 5719
Marko Mikulicic 0:c0ecb8bf28eb 5720 V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op);
Marko Mikulicic 0:c0ecb8bf28eb 5721
Marko Mikulicic 0:c0ecb8bf28eb 5722 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 5723 V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5724 int line_no);
Marko Mikulicic 0:c0ecb8bf28eb 5725 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5726
Marko Mikulicic 0:c0ecb8bf28eb 5727 /*
Marko Mikulicic 0:c0ecb8bf28eb 5728 * Add a literal to the bcode literal table, or just decide that the literal
Marko Mikulicic 0:c0ecb8bf28eb 5729 * should be inlined into `ops`. See `lit_t` for details.
Marko Mikulicic 0:c0ecb8bf28eb 5730 */
Marko Mikulicic 0:c0ecb8bf28eb 5731 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5732 lit_t bcode_add_lit(struct bcode_builder *bbuilder, v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 5733
Marko Mikulicic 0:c0ecb8bf28eb 5734 /* disabled because of short lits */
Marko Mikulicic 0:c0ecb8bf28eb 5735 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 5736 V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx);
Marko Mikulicic 0:c0ecb8bf28eb 5737 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5738
Marko Mikulicic 0:c0ecb8bf28eb 5739 /*
Marko Mikulicic 0:c0ecb8bf28eb 5740 * Emit an opcode `op`, and handle the literal `lit` (see `bcode_add_lit()`,
Marko Mikulicic 0:c0ecb8bf28eb 5741 * `lit_t`). Depending on the literal storage mode (see `enum lit_mode`), this
Marko Mikulicic 0:c0ecb8bf28eb 5742 * function either emits literal table index or inlines the literal directly
Marko Mikulicic 0:c0ecb8bf28eb 5743 * into `ops.`
Marko Mikulicic 0:c0ecb8bf28eb 5744 */
Marko Mikulicic 0:c0ecb8bf28eb 5745 V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op,
Marko Mikulicic 0:c0ecb8bf28eb 5746 lit_t lit);
Marko Mikulicic 0:c0ecb8bf28eb 5747
Marko Mikulicic 0:c0ecb8bf28eb 5748 /* Helper function, equivalent of `bcode_op_lit(bbuilder, OP_PUSH_LIT, lit)` */
Marko Mikulicic 0:c0ecb8bf28eb 5749 V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit);
Marko Mikulicic 0:c0ecb8bf28eb 5750
Marko Mikulicic 0:c0ecb8bf28eb 5751 /*
Marko Mikulicic 0:c0ecb8bf28eb 5752 * Add name to bcode. If `idx` is null, a name is appended to the end of the
Marko Mikulicic 0:c0ecb8bf28eb 5753 * `bcode->ops.buf`. If `idx` is provided, it should point to the index at
Marko Mikulicic 0:c0ecb8bf28eb 5754 * which new name should be inserted; and it is updated by the
Marko Mikulicic 0:c0ecb8bf28eb 5755 * `bcode_add_name()` to point right after newly added name.
Marko Mikulicic 0:c0ecb8bf28eb 5756 *
Marko Mikulicic 0:c0ecb8bf28eb 5757 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5758 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5759 */
Marko Mikulicic 0:c0ecb8bf28eb 5760 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5761 /*V7_PRIVATE*/ enum v7_err
Marko Mikulicic 0:c0ecb8bf28eb 5762 bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 5763 size_t *idx);
Marko Mikulicic 0:c0ecb8bf28eb 5764
Marko Mikulicic 0:c0ecb8bf28eb 5765 /*
Marko Mikulicic 0:c0ecb8bf28eb 5766 * Takes a pointer to the beginning of `ops` buffer and names count, returns
Marko Mikulicic 0:c0ecb8bf28eb 5767 * a pointer where actual opcodes begin (i.e. skips names).
Marko Mikulicic 0:c0ecb8bf28eb 5768 *
Marko Mikulicic 0:c0ecb8bf28eb 5769 * It takes two distinct arguments instead of just `struct bcode` pointer,
Marko Mikulicic 0:c0ecb8bf28eb 5770 * because during bcode building `ops` is stored in builder.
Marko Mikulicic 0:c0ecb8bf28eb 5771 *
Marko Mikulicic 0:c0ecb8bf28eb 5772 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5773 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5774 */
Marko Mikulicic 0:c0ecb8bf28eb 5775 /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 5776
Marko Mikulicic 0:c0ecb8bf28eb 5777 /*
Marko Mikulicic 0:c0ecb8bf28eb 5778 * Given a pointer to `ops` (which should be `bcode->ops` or a pointer returned
Marko Mikulicic 0:c0ecb8bf28eb 5779 * from previous invocation of `bcode_next_name()`), yields a name string via
Marko Mikulicic 0:c0ecb8bf28eb 5780 * arguments `pname`, `plen`.
Marko Mikulicic 0:c0ecb8bf28eb 5781 *
Marko Mikulicic 0:c0ecb8bf28eb 5782 * Returns a pointer that should be given to `bcode_next_name()` to get a next
Marko Mikulicic 0:c0ecb8bf28eb 5783 * string (Whether there is a next string should be determined via the
Marko Mikulicic 0:c0ecb8bf28eb 5784 * `names_cnt`; since if there are no more names, this function will return an
Marko Mikulicic 0:c0ecb8bf28eb 5785 * invalid non-null pointer as next name pointer)
Marko Mikulicic 0:c0ecb8bf28eb 5786 */
Marko Mikulicic 0:c0ecb8bf28eb 5787 V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen);
Marko Mikulicic 0:c0ecb8bf28eb 5788
Marko Mikulicic 0:c0ecb8bf28eb 5789 /*
Marko Mikulicic 0:c0ecb8bf28eb 5790 * Like `bcode_next_name()`, but instead of yielding a C string, it yields a
Marko Mikulicic 0:c0ecb8bf28eb 5791 * `val_t` value (via `res`).
Marko Mikulicic 0:c0ecb8bf28eb 5792 */
Marko Mikulicic 0:c0ecb8bf28eb 5793 V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5794 char *ops, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5795
Marko Mikulicic 0:c0ecb8bf28eb 5796 V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 5797
Marko Mikulicic 0:c0ecb8bf28eb 5798 V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 5799 /*
Marko Mikulicic 0:c0ecb8bf28eb 5800 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5801 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5802 */
Marko Mikulicic 0:c0ecb8bf28eb 5803 /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5804 uint8_t op);
Marko Mikulicic 0:c0ecb8bf28eb 5805 /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5806 bcode_off_t label, bcode_off_t target);
Marko Mikulicic 0:c0ecb8bf28eb 5807
Marko Mikulicic 0:c0ecb8bf28eb 5808 V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value);
Marko Mikulicic 0:c0ecb8bf28eb 5809 /*
Marko Mikulicic 0:c0ecb8bf28eb 5810 * Reads varint-encoded integer from the provided pointer, and adjusts
Marko Mikulicic 0:c0ecb8bf28eb 5811 * the pointer appropriately
Marko Mikulicic 0:c0ecb8bf28eb 5812 */
Marko Mikulicic 0:c0ecb8bf28eb 5813 V7_PRIVATE size_t bcode_get_varint(char **ops);
Marko Mikulicic 0:c0ecb8bf28eb 5814
Marko Mikulicic 0:c0ecb8bf28eb 5815 /*
Marko Mikulicic 0:c0ecb8bf28eb 5816 * Decode a literal value from a string of opcodes and update the cursor to
Marko Mikulicic 0:c0ecb8bf28eb 5817 * point past it
Marko Mikulicic 0:c0ecb8bf28eb 5818 */
Marko Mikulicic 0:c0ecb8bf28eb 5819 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5820 v7_val_t bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops);
Marko Mikulicic 0:c0ecb8bf28eb 5821
Marko Mikulicic 0:c0ecb8bf28eb 5822 #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 5823 V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5824 char **ops);
Marko Mikulicic 0:c0ecb8bf28eb 5825 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5826
Marko Mikulicic 0:c0ecb8bf28eb 5827 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5828 }
Marko Mikulicic 0:c0ecb8bf28eb 5829 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5830
Marko Mikulicic 0:c0ecb8bf28eb 5831 #endif /* CS_V7_SRC_BCODE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5832 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5833 #line 1 "v7/src/gc_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 5834 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5835 /*
Marko Mikulicic 0:c0ecb8bf28eb 5836 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5837 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5838 */
Marko Mikulicic 0:c0ecb8bf28eb 5839
Marko Mikulicic 0:c0ecb8bf28eb 5840 /*
Marko Mikulicic 0:c0ecb8bf28eb 5841 * === Garbage Collector
Marko Mikulicic 0:c0ecb8bf28eb 5842 */
Marko Mikulicic 0:c0ecb8bf28eb 5843
Marko Mikulicic 0:c0ecb8bf28eb 5844 #ifndef CS_V7_SRC_GC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5845 #define CS_V7_SRC_GC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5846
Marko Mikulicic 0:c0ecb8bf28eb 5847 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5848
Marko Mikulicic 0:c0ecb8bf28eb 5849 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5850 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5851 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5852
Marko Mikulicic 0:c0ecb8bf28eb 5853 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 5854
Marko Mikulicic 0:c0ecb8bf28eb 5855 /* Heap metric id, see `v7_heap_stat()` */
Marko Mikulicic 0:c0ecb8bf28eb 5856 enum v7_heap_stat_what {
Marko Mikulicic 0:c0ecb8bf28eb 5857 V7_HEAP_STAT_HEAP_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5858 V7_HEAP_STAT_HEAP_USED,
Marko Mikulicic 0:c0ecb8bf28eb 5859 V7_HEAP_STAT_STRING_HEAP_RESERVED,
Marko Mikulicic 0:c0ecb8bf28eb 5860 V7_HEAP_STAT_STRING_HEAP_USED,
Marko Mikulicic 0:c0ecb8bf28eb 5861 V7_HEAP_STAT_OBJ_HEAP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 5862 V7_HEAP_STAT_OBJ_HEAP_FREE,
Marko Mikulicic 0:c0ecb8bf28eb 5863 V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5864 V7_HEAP_STAT_FUNC_HEAP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 5865 V7_HEAP_STAT_FUNC_HEAP_FREE,
Marko Mikulicic 0:c0ecb8bf28eb 5866 V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5867 V7_HEAP_STAT_PROP_HEAP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 5868 V7_HEAP_STAT_PROP_HEAP_FREE,
Marko Mikulicic 0:c0ecb8bf28eb 5869 V7_HEAP_STAT_PROP_HEAP_CELL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5870 V7_HEAP_STAT_FUNC_AST_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5871 V7_HEAP_STAT_BCODE_OPS_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5872 V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5873 V7_HEAP_STAT_BCODE_LIT_DESER_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5874 V7_HEAP_STAT_FUNC_OWNED,
Marko Mikulicic 0:c0ecb8bf28eb 5875 V7_HEAP_STAT_FUNC_OWNED_MAX
Marko Mikulicic 0:c0ecb8bf28eb 5876 };
Marko Mikulicic 0:c0ecb8bf28eb 5877
Marko Mikulicic 0:c0ecb8bf28eb 5878 /* Returns a given heap statistics */
Marko Mikulicic 0:c0ecb8bf28eb 5879 int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what);
Marko Mikulicic 0:c0ecb8bf28eb 5880 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5881
Marko Mikulicic 0:c0ecb8bf28eb 5882 /*
Marko Mikulicic 0:c0ecb8bf28eb 5883 * Perform garbage collection.
Marko Mikulicic 0:c0ecb8bf28eb 5884 * Pass true to full in order to reclaim unused heap back to the OS.
Marko Mikulicic 0:c0ecb8bf28eb 5885 */
Marko Mikulicic 0:c0ecb8bf28eb 5886 void v7_gc(struct v7 *v7, int full);
Marko Mikulicic 0:c0ecb8bf28eb 5887
Marko Mikulicic 0:c0ecb8bf28eb 5888 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5889 }
Marko Mikulicic 0:c0ecb8bf28eb 5890 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5891
Marko Mikulicic 0:c0ecb8bf28eb 5892 #endif /* CS_V7_SRC_GC_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5893 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5894 #line 1 "v7/src/gc.h"
Marko Mikulicic 0:c0ecb8bf28eb 5895 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5896 /*
Marko Mikulicic 0:c0ecb8bf28eb 5897 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5898 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5899 */
Marko Mikulicic 0:c0ecb8bf28eb 5900
Marko Mikulicic 0:c0ecb8bf28eb 5901 #ifndef CS_V7_SRC_GC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5902 #define CS_V7_SRC_GC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5903
Marko Mikulicic 0:c0ecb8bf28eb 5904 /* Amalgamated: #include "v7/src/gc_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5905
Marko Mikulicic 0:c0ecb8bf28eb 5906 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5907 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5908
Marko Mikulicic 0:c0ecb8bf28eb 5909 /*
Marko Mikulicic 0:c0ecb8bf28eb 5910 * Macros for marking reachable things: use bit 0.
Marko Mikulicic 0:c0ecb8bf28eb 5911 */
Marko Mikulicic 0:c0ecb8bf28eb 5912 #define MARK(p) (((struct gc_cell *) (p))->head.word |= 1)
Marko Mikulicic 0:c0ecb8bf28eb 5913 #define UNMARK(p) (((struct gc_cell *) (p))->head.word &= ~1)
Marko Mikulicic 0:c0ecb8bf28eb 5914 #define MARKED(p) (((struct gc_cell *) (p))->head.word & 1)
Marko Mikulicic 0:c0ecb8bf28eb 5915
Marko Mikulicic 0:c0ecb8bf28eb 5916 /*
Marko Mikulicic 0:c0ecb8bf28eb 5917 * Similar to `MARK()` / `UNMARK()` / `MARKED()`, but `.._FREE` counterparts
Marko Mikulicic 0:c0ecb8bf28eb 5918 * are intended to mark free cells (as opposed to used ones), so they use
Marko Mikulicic 0:c0ecb8bf28eb 5919 * bit 1.
Marko Mikulicic 0:c0ecb8bf28eb 5920 */
Marko Mikulicic 0:c0ecb8bf28eb 5921 #define MARK_FREE(p) (((struct gc_cell *) (p))->head.word |= 2)
Marko Mikulicic 0:c0ecb8bf28eb 5922 #define UNMARK_FREE(p) (((struct gc_cell *) (p))->head.word &= ~2)
Marko Mikulicic 0:c0ecb8bf28eb 5923 #define MARKED_FREE(p) (((struct gc_cell *) (p))->head.word & 2)
Marko Mikulicic 0:c0ecb8bf28eb 5924
Marko Mikulicic 0:c0ecb8bf28eb 5925 /*
Marko Mikulicic 0:c0ecb8bf28eb 5926 * performs arithmetics on gc_cell pointers as if they were arena->cell_size
Marko Mikulicic 0:c0ecb8bf28eb 5927 * bytes wide
Marko Mikulicic 0:c0ecb8bf28eb 5928 */
Marko Mikulicic 0:c0ecb8bf28eb 5929 #define GC_CELL_OP(arena, cell, op, arg) \
Marko Mikulicic 0:c0ecb8bf28eb 5930 ((struct gc_cell *) (((char *) (cell)) op((arg) * (arena)->cell_size)))
Marko Mikulicic 0:c0ecb8bf28eb 5931
Marko Mikulicic 0:c0ecb8bf28eb 5932 struct gc_tmp_frame {
Marko Mikulicic 0:c0ecb8bf28eb 5933 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 5934 size_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 5935 };
Marko Mikulicic 0:c0ecb8bf28eb 5936
Marko Mikulicic 0:c0ecb8bf28eb 5937 struct gc_cell {
Marko Mikulicic 0:c0ecb8bf28eb 5938 union {
Marko Mikulicic 0:c0ecb8bf28eb 5939 struct gc_cell *link;
Marko Mikulicic 0:c0ecb8bf28eb 5940 uintptr_t word;
Marko Mikulicic 0:c0ecb8bf28eb 5941 } head;
Marko Mikulicic 0:c0ecb8bf28eb 5942 };
Marko Mikulicic 0:c0ecb8bf28eb 5943
Marko Mikulicic 0:c0ecb8bf28eb 5944 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5945 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5946 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5947
Marko Mikulicic 0:c0ecb8bf28eb 5948 V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5949 V7_PRIVATE struct v7_property *new_property(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5950 V7_PRIVATE struct v7_js_function *new_function(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5951
Marko Mikulicic 0:c0ecb8bf28eb 5952 V7_PRIVATE void gc_mark(struct v7 *, val_t);
Marko Mikulicic 0:c0ecb8bf28eb 5953
Marko Mikulicic 0:c0ecb8bf28eb 5954 V7_PRIVATE void gc_arena_init(struct gc_arena *, size_t, size_t, size_t,
Marko Mikulicic 0:c0ecb8bf28eb 5955 const char *);
Marko Mikulicic 0:c0ecb8bf28eb 5956 V7_PRIVATE void gc_arena_destroy(struct v7 *, struct gc_arena *a);
Marko Mikulicic 0:c0ecb8bf28eb 5957 V7_PRIVATE void gc_sweep(struct v7 *, struct gc_arena *, size_t);
Marko Mikulicic 0:c0ecb8bf28eb 5958 V7_PRIVATE void *gc_alloc_cell(struct v7 *, struct gc_arena *);
Marko Mikulicic 0:c0ecb8bf28eb 5959
Marko Mikulicic 0:c0ecb8bf28eb 5960 V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5961 V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *);
Marko Mikulicic 0:c0ecb8bf28eb 5962 V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *, val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 5963
Marko Mikulicic 0:c0ecb8bf28eb 5964 V7_PRIVATE void compute_need_gc(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5965 /* perform gc if not inhibited */
Marko Mikulicic 0:c0ecb8bf28eb 5966 V7_PRIVATE int maybe_gc(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5967
Marko Mikulicic 0:c0ecb8bf28eb 5968 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 5969 V7_PRIVATE uint16_t
Marko Mikulicic 0:c0ecb8bf28eb 5970 gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 5971 V7_PRIVATE int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n);
Marko Mikulicic 0:c0ecb8bf28eb 5972 V7_PRIVATE void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n);
Marko Mikulicic 0:c0ecb8bf28eb 5973 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5974
Marko Mikulicic 0:c0ecb8bf28eb 5975 V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 5976
Marko Mikulicic 0:c0ecb8bf28eb 5977 /* return 0 if v is an object/function with a bad pointer */
Marko Mikulicic 0:c0ecb8bf28eb 5978 V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 5979
Marko Mikulicic 0:c0ecb8bf28eb 5980 /* checks whether a pointer is within the ranges of an arena */
Marko Mikulicic 0:c0ecb8bf28eb 5981 V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *p);
Marko Mikulicic 0:c0ecb8bf28eb 5982
Marko Mikulicic 0:c0ecb8bf28eb 5983 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 5984 V7_PRIVATE size_t gc_arena_size(struct gc_arena *);
Marko Mikulicic 0:c0ecb8bf28eb 5985 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5986
Marko Mikulicic 0:c0ecb8bf28eb 5987 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5988 }
Marko Mikulicic 0:c0ecb8bf28eb 5989 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5990
Marko Mikulicic 0:c0ecb8bf28eb 5991 #endif /* CS_V7_SRC_GC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5992 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5993 #line 1 "v7/src/regexp_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 5994 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5995 /*
Marko Mikulicic 0:c0ecb8bf28eb 5996 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5997 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5998 */
Marko Mikulicic 0:c0ecb8bf28eb 5999
Marko Mikulicic 0:c0ecb8bf28eb 6000 /*
Marko Mikulicic 0:c0ecb8bf28eb 6001 * === RegExp
Marko Mikulicic 0:c0ecb8bf28eb 6002 */
Marko Mikulicic 0:c0ecb8bf28eb 6003
Marko Mikulicic 0:c0ecb8bf28eb 6004 #ifndef CS_V7_SRC_REGEXP_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6005 #define CS_V7_SRC_REGEXP_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6006
Marko Mikulicic 0:c0ecb8bf28eb 6007 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6008
Marko Mikulicic 0:c0ecb8bf28eb 6009 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6010 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6011 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6012
Marko Mikulicic 0:c0ecb8bf28eb 6013 /*
Marko Mikulicic 0:c0ecb8bf28eb 6014 * Make RegExp object.
Marko Mikulicic 0:c0ecb8bf28eb 6015 * `regex`, `regex_len` specify a pattern, `flags` and `flags_len` specify
Marko Mikulicic 0:c0ecb8bf28eb 6016 * flags. Both utf8 encoded. For example, `regex` is `(.+)`, `flags` is `gi`.
Marko Mikulicic 0:c0ecb8bf28eb 6017 * If `regex_len` is ~0, `regex` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 6018 * `strlen(regex)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 6019 */
Marko Mikulicic 0:c0ecb8bf28eb 6020 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6021 enum v7_err v7_mk_regexp(struct v7 *v7, const char *regex, size_t regex_len,
Marko Mikulicic 0:c0ecb8bf28eb 6022 const char *flags, size_t flags_len, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6023
Marko Mikulicic 0:c0ecb8bf28eb 6024 /* Returns true if given value is a JavaScript RegExp object*/
Marko Mikulicic 0:c0ecb8bf28eb 6025 int v7_is_regexp(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6026
Marko Mikulicic 0:c0ecb8bf28eb 6027 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6028 }
Marko Mikulicic 0:c0ecb8bf28eb 6029 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6030
Marko Mikulicic 0:c0ecb8bf28eb 6031 #endif /* CS_V7_SRC_REGEXP_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6032 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6033 #line 1 "v7/src/regexp.h"
Marko Mikulicic 0:c0ecb8bf28eb 6034 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6035 /*
Marko Mikulicic 0:c0ecb8bf28eb 6036 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6037 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6038 */
Marko Mikulicic 0:c0ecb8bf28eb 6039
Marko Mikulicic 0:c0ecb8bf28eb 6040 #ifndef CS_V7_SRC_REGEXP_H_
Marko Mikulicic 0:c0ecb8bf28eb 6041 #define CS_V7_SRC_REGEXP_H_
Marko Mikulicic 0:c0ecb8bf28eb 6042
Marko Mikulicic 0:c0ecb8bf28eb 6043 /* Amalgamated: #include "v7/src/regexp_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6044
Marko Mikulicic 0:c0ecb8bf28eb 6045 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6046
Marko Mikulicic 0:c0ecb8bf28eb 6047 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 6048
Marko Mikulicic 0:c0ecb8bf28eb 6049 /*
Marko Mikulicic 0:c0ecb8bf28eb 6050 * Maximum number of flags returned by get_regexp_flags_str().
Marko Mikulicic 0:c0ecb8bf28eb 6051 * NOTE: does not include null-terminate byte.
Marko Mikulicic 0:c0ecb8bf28eb 6052 */
Marko Mikulicic 0:c0ecb8bf28eb 6053 #define _V7_REGEXP_MAX_FLAGS_LEN 3
Marko Mikulicic 0:c0ecb8bf28eb 6054
Marko Mikulicic 0:c0ecb8bf28eb 6055 struct v7_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 6056
Marko Mikulicic 0:c0ecb8bf28eb 6057 V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *, v7_val_t);
Marko Mikulicic 0:c0ecb8bf28eb 6058
Marko Mikulicic 0:c0ecb8bf28eb 6059 /*
Marko Mikulicic 0:c0ecb8bf28eb 6060 * Generates a string containing regexp flags, e.g. "gi".
Marko Mikulicic 0:c0ecb8bf28eb 6061 *
Marko Mikulicic 0:c0ecb8bf28eb 6062 * `buf` should point to a buffer of minimum `_V7_REGEXP_MAX_FLAGS_LEN` bytes.
Marko Mikulicic 0:c0ecb8bf28eb 6063 * Returns length of the resulted string (saved into `buf`)
Marko Mikulicic 0:c0ecb8bf28eb 6064 */
Marko Mikulicic 0:c0ecb8bf28eb 6065 V7_PRIVATE size_t
Marko Mikulicic 0:c0ecb8bf28eb 6066 get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf);
Marko Mikulicic 0:c0ecb8bf28eb 6067 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 6068
Marko Mikulicic 0:c0ecb8bf28eb 6069 #endif /* CS_V7_SRC_REGEXP_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6070 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6071 #line 1 "v7/src/function_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 6072 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6073 /*
Marko Mikulicic 0:c0ecb8bf28eb 6074 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6075 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6076 */
Marko Mikulicic 0:c0ecb8bf28eb 6077
Marko Mikulicic 0:c0ecb8bf28eb 6078 /*
Marko Mikulicic 0:c0ecb8bf28eb 6079 * === Functions
Marko Mikulicic 0:c0ecb8bf28eb 6080 */
Marko Mikulicic 0:c0ecb8bf28eb 6081
Marko Mikulicic 0:c0ecb8bf28eb 6082 #ifndef CS_V7_SRC_FUNCTION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6083 #define CS_V7_SRC_FUNCTION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6084
Marko Mikulicic 0:c0ecb8bf28eb 6085 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6086
Marko Mikulicic 0:c0ecb8bf28eb 6087 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6088 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6089 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6090
Marko Mikulicic 0:c0ecb8bf28eb 6091 /*
Marko Mikulicic 0:c0ecb8bf28eb 6092 * Make a JS function object backed by a cfunction.
Marko Mikulicic 0:c0ecb8bf28eb 6093 *
Marko Mikulicic 0:c0ecb8bf28eb 6094 * `func` is a C callback.
Marko Mikulicic 0:c0ecb8bf28eb 6095 *
Marko Mikulicic 0:c0ecb8bf28eb 6096 * A function object is JS object having the Function prototype that holds a
Marko Mikulicic 0:c0ecb8bf28eb 6097 * cfunction value in a hidden property.
Marko Mikulicic 0:c0ecb8bf28eb 6098 *
Marko Mikulicic 0:c0ecb8bf28eb 6099 * The function object will have a `prototype` property holding an object that
Marko Mikulicic 0:c0ecb8bf28eb 6100 * will be used as the prototype of objects created when calling the function
Marko Mikulicic 0:c0ecb8bf28eb 6101 * with the `new` operator.
Marko Mikulicic 0:c0ecb8bf28eb 6102 */
Marko Mikulicic 0:c0ecb8bf28eb 6103 v7_val_t v7_mk_function(struct v7 *, v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 6104
Marko Mikulicic 0:c0ecb8bf28eb 6105 /*
Marko Mikulicic 0:c0ecb8bf28eb 6106 * Make f a JS function with specified prototype `proto`, so that the resulting
Marko Mikulicic 0:c0ecb8bf28eb 6107 * function is better suited for the usage as a constructor.
Marko Mikulicic 0:c0ecb8bf28eb 6108 */
Marko Mikulicic 0:c0ecb8bf28eb 6109 v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f,
Marko Mikulicic 0:c0ecb8bf28eb 6110 v7_val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 6111
Marko Mikulicic 0:c0ecb8bf28eb 6112 /*
Marko Mikulicic 0:c0ecb8bf28eb 6113 * Make a JS value that holds C/C++ callback pointer.
Marko Mikulicic 0:c0ecb8bf28eb 6114 *
Marko Mikulicic 0:c0ecb8bf28eb 6115 * CAUTION: This is a low-level function value. It's not a real object and
Marko Mikulicic 0:c0ecb8bf28eb 6116 * cannot hold user defined properties. You should use `v7_mk_function` unless
Marko Mikulicic 0:c0ecb8bf28eb 6117 * you know what you're doing.
Marko Mikulicic 0:c0ecb8bf28eb 6118 */
Marko Mikulicic 0:c0ecb8bf28eb 6119 v7_val_t v7_mk_cfunction(v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 6120
Marko Mikulicic 0:c0ecb8bf28eb 6121 /*
Marko Mikulicic 0:c0ecb8bf28eb 6122 * Returns true if given value is callable (i.e. it's either a JS function or
Marko Mikulicic 0:c0ecb8bf28eb 6123 * cfunction)
Marko Mikulicic 0:c0ecb8bf28eb 6124 */
Marko Mikulicic 0:c0ecb8bf28eb 6125 int v7_is_callable(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6126
Marko Mikulicic 0:c0ecb8bf28eb 6127 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6128 }
Marko Mikulicic 0:c0ecb8bf28eb 6129 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6130
Marko Mikulicic 0:c0ecb8bf28eb 6131 #endif /* CS_V7_SRC_FUNCTION_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6132 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6133 #line 1 "v7/src/function.h"
Marko Mikulicic 0:c0ecb8bf28eb 6134 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6135 /*
Marko Mikulicic 0:c0ecb8bf28eb 6136 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6137 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6138 */
Marko Mikulicic 0:c0ecb8bf28eb 6139
Marko Mikulicic 0:c0ecb8bf28eb 6140 #ifndef CS_V7_SRC_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 6141 #define CS_V7_SRC_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 6142
Marko Mikulicic 0:c0ecb8bf28eb 6143 /* Amalgamated: #include "v7/src/function_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6144
Marko Mikulicic 0:c0ecb8bf28eb 6145 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6146 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6147
Marko Mikulicic 0:c0ecb8bf28eb 6148 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6149 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6150 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6151
Marko Mikulicic 0:c0ecb8bf28eb 6152 V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6153 V7_PRIVATE val_t
Marko Mikulicic 0:c0ecb8bf28eb 6154 mk_js_function(struct v7 *v7, struct v7_generic_object *scope, val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 6155 V7_PRIVATE int is_js_function(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6156 V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f);
Marko Mikulicic 0:c0ecb8bf28eb 6157
Marko Mikulicic 0:c0ecb8bf28eb 6158 /* Returns true if given value holds a pointer to C callback */
Marko Mikulicic 0:c0ecb8bf28eb 6159 V7_PRIVATE int is_cfunction_lite(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6160
Marko Mikulicic 0:c0ecb8bf28eb 6161 /* Returns true if given value holds an object which represents C callback */
Marko Mikulicic 0:c0ecb8bf28eb 6162 V7_PRIVATE int is_cfunction_obj(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6163
Marko Mikulicic 0:c0ecb8bf28eb 6164 /*
Marko Mikulicic 0:c0ecb8bf28eb 6165 * Returns `v7_cfunction_t *` callback pointer stored in `v7_val_t`, or NULL
Marko Mikulicic 0:c0ecb8bf28eb 6166 * if given value is neither cfunction pointer nor cfunction object.
Marko Mikulicic 0:c0ecb8bf28eb 6167 */
Marko Mikulicic 0:c0ecb8bf28eb 6168 V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6169
Marko Mikulicic 0:c0ecb8bf28eb 6170 /*
Marko Mikulicic 0:c0ecb8bf28eb 6171 * Like v7_mk_function but also sets the function's `length` property.
Marko Mikulicic 0:c0ecb8bf28eb 6172 *
Marko Mikulicic 0:c0ecb8bf28eb 6173 * The `length` property is useful for introspection and the stdlib defines it
Marko Mikulicic 0:c0ecb8bf28eb 6174 * for many core functions mostly because the ECMA test suite requires it and we
Marko Mikulicic 0:c0ecb8bf28eb 6175 * don't want to skip otherwise useful tests just because the `length` property
Marko Mikulicic 0:c0ecb8bf28eb 6176 * check fails early in the test. User defined functions don't need to specify
Marko Mikulicic 0:c0ecb8bf28eb 6177 * the length and passing -1 is a safe choice, as it will also reduce the
Marko Mikulicic 0:c0ecb8bf28eb 6178 * footprint.
Marko Mikulicic 0:c0ecb8bf28eb 6179 *
Marko Mikulicic 0:c0ecb8bf28eb 6180 * The subtle difference between set `length` explicitly to 0 rather than
Marko Mikulicic 0:c0ecb8bf28eb 6181 * just defaulting the `0` value from the prototype is that in the former case
Marko Mikulicic 0:c0ecb8bf28eb 6182 * the property cannot be change since it's read only. This again, is important
Marko Mikulicic 0:c0ecb8bf28eb 6183 * only for ecma compliance and your user code might or might not find this
Marko Mikulicic 0:c0ecb8bf28eb 6184 * relevant.
Marko Mikulicic 0:c0ecb8bf28eb 6185 *
Marko Mikulicic 0:c0ecb8bf28eb 6186 * NODO(lsm): please don't combine v7_mk_function_arg and v7_mk_function
Marko Mikulicic 0:c0ecb8bf28eb 6187 * into one function. Currently `num_args` is useful only internally. External
Marko Mikulicic 0:c0ecb8bf28eb 6188 * users can just use `v7_def` to set the length.
Marko Mikulicic 0:c0ecb8bf28eb 6189 */
Marko Mikulicic 0:c0ecb8bf28eb 6190 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 6191 v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *func, int num_args);
Marko Mikulicic 0:c0ecb8bf28eb 6192
Marko Mikulicic 0:c0ecb8bf28eb 6193 /*
Marko Mikulicic 0:c0ecb8bf28eb 6194 * Like v7_mk_function_with_proto but also sets the function's `length`
Marko Mikulicic 0:c0ecb8bf28eb 6195 *property.
Marko Mikulicic 0:c0ecb8bf28eb 6196 *
Marko Mikulicic 0:c0ecb8bf28eb 6197 * NODO(lsm): please don't combine mk_cfunction_obj_with_proto and
Marko Mikulicic 0:c0ecb8bf28eb 6198 * v7_mk_function_with_proto.
Marko Mikulicic 0:c0ecb8bf28eb 6199 * into one function. Currently `num_args` is useful only internally. External
Marko Mikulicic 0:c0ecb8bf28eb 6200 * users can just use `v7_def` to set the length.
Marko Mikulicic 0:c0ecb8bf28eb 6201 */
Marko Mikulicic 0:c0ecb8bf28eb 6202 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 6203 v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7, v7_cfunction_t *f,
Marko Mikulicic 0:c0ecb8bf28eb 6204 int num_args, v7_val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 6205
Marko Mikulicic 0:c0ecb8bf28eb 6206 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6207 }
Marko Mikulicic 0:c0ecb8bf28eb 6208 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6209
Marko Mikulicic 0:c0ecb8bf28eb 6210 #endif /* CS_V7_SRC_FUNCTION_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6211 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6212 #line 1 "v7/src/util_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 6213 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6214 /*
Marko Mikulicic 0:c0ecb8bf28eb 6215 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6216 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6217 */
Marko Mikulicic 0:c0ecb8bf28eb 6218
Marko Mikulicic 0:c0ecb8bf28eb 6219 /*
Marko Mikulicic 0:c0ecb8bf28eb 6220 * === Utility functions
Marko Mikulicic 0:c0ecb8bf28eb 6221 */
Marko Mikulicic 0:c0ecb8bf28eb 6222
Marko Mikulicic 0:c0ecb8bf28eb 6223 #ifndef CS_V7_SRC_UTIL_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6224 #define CS_V7_SRC_UTIL_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6225
Marko Mikulicic 0:c0ecb8bf28eb 6226 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6227
Marko Mikulicic 0:c0ecb8bf28eb 6228 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6229 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6230 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6231
Marko Mikulicic 0:c0ecb8bf28eb 6232 /* Output a string representation of the value to stdout.
Marko Mikulicic 0:c0ecb8bf28eb 6233 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6234 void v7_print(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6235
Marko Mikulicic 0:c0ecb8bf28eb 6236 /* Output a string representation of the value to stdout followed by a newline.
Marko Mikulicic 0:c0ecb8bf28eb 6237 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6238 void v7_println(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6239
Marko Mikulicic 0:c0ecb8bf28eb 6240 /* Output a string representation of the value to a file.
Marko Mikulicic 0:c0ecb8bf28eb 6241 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6242 void v7_fprint(FILE *f, struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6243
Marko Mikulicic 0:c0ecb8bf28eb 6244 /* Output a string representation of the value to a file followed by a newline.
Marko Mikulicic 0:c0ecb8bf28eb 6245 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6246 void v7_fprintln(FILE *f, struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6247
Marko Mikulicic 0:c0ecb8bf28eb 6248 /* Output stack trace recorded in the exception `e` to file `f` */
Marko Mikulicic 0:c0ecb8bf28eb 6249 void v7_fprint_stack_trace(FILE *f, struct v7 *v7, v7_val_t e);
Marko Mikulicic 0:c0ecb8bf28eb 6250
Marko Mikulicic 0:c0ecb8bf28eb 6251 /* Output error object message and possibly stack trace to f */
Marko Mikulicic 0:c0ecb8bf28eb 6252 void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, v7_val_t e);
Marko Mikulicic 0:c0ecb8bf28eb 6253
Marko Mikulicic 0:c0ecb8bf28eb 6254 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6255
Marko Mikulicic 0:c0ecb8bf28eb 6256 struct v7_property;
Marko Mikulicic 0:c0ecb8bf28eb 6257
Marko Mikulicic 0:c0ecb8bf28eb 6258 /*
Marko Mikulicic 0:c0ecb8bf28eb 6259 * C callback, analogue of JS callback `getOwnPropertyDescriptor()`.
Marko Mikulicic 0:c0ecb8bf28eb 6260 * Callbacks of this type are used for C API only, see `m7_mk_proxy()`.
Marko Mikulicic 0:c0ecb8bf28eb 6261 *
Marko Mikulicic 0:c0ecb8bf28eb 6262 * `name` is the name of the property, and the function should fill `attrs` and
Marko Mikulicic 0:c0ecb8bf28eb 6263 * `value` with the property data. Before this callback is called, `attrs` is
Marko Mikulicic 0:c0ecb8bf28eb 6264 * set to 0, and `value` is `V7_UNDEFINED`.
Marko Mikulicic 0:c0ecb8bf28eb 6265 *
Marko Mikulicic 0:c0ecb8bf28eb 6266 * It should return non-zero if the property should be considered existing, or
Marko Mikulicic 0:c0ecb8bf28eb 6267 * zero otherwise.
Marko Mikulicic 0:c0ecb8bf28eb 6268 *
Marko Mikulicic 0:c0ecb8bf28eb 6269 * You can inspect the property attributes with the `V7_PROP_ATTR_IS_*` macros.
Marko Mikulicic 0:c0ecb8bf28eb 6270 */
Marko Mikulicic 0:c0ecb8bf28eb 6271 typedef int(v7_get_own_prop_desc_cb_t)(struct v7 *v7, v7_val_t target,
Marko Mikulicic 0:c0ecb8bf28eb 6272 v7_val_t name, v7_prop_attr_t *attrs,
Marko Mikulicic 0:c0ecb8bf28eb 6273 v7_val_t *value);
Marko Mikulicic 0:c0ecb8bf28eb 6274
Marko Mikulicic 0:c0ecb8bf28eb 6275 /* Handler for `v7_mk_proxy()`; each item is a cfunction */
Marko Mikulicic 0:c0ecb8bf28eb 6276 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 6277 v7_cfunction_t *get;
Marko Mikulicic 0:c0ecb8bf28eb 6278 v7_cfunction_t *set;
Marko Mikulicic 0:c0ecb8bf28eb 6279 v7_cfunction_t *own_keys;
Marko Mikulicic 0:c0ecb8bf28eb 6280 v7_get_own_prop_desc_cb_t *get_own_prop_desc;
Marko Mikulicic 0:c0ecb8bf28eb 6281 } v7_proxy_hnd_t;
Marko Mikulicic 0:c0ecb8bf28eb 6282
Marko Mikulicic 0:c0ecb8bf28eb 6283 /*
Marko Mikulicic 0:c0ecb8bf28eb 6284 * Create a Proxy object, see:
Marko Mikulicic 0:c0ecb8bf28eb 6285 * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6286 *
Marko Mikulicic 0:c0ecb8bf28eb 6287 * Only two traps are implemented so far: `get()` and `set()`. Note that
Marko Mikulicic 0:c0ecb8bf28eb 6288 * `Object.defineProperty()` bypasses the `set()` trap.
Marko Mikulicic 0:c0ecb8bf28eb 6289 *
Marko Mikulicic 0:c0ecb8bf28eb 6290 * If `target` is not an object, the empty object will be used, so it's safe
Marko Mikulicic 0:c0ecb8bf28eb 6291 * to pass `V7_UNDEFINED` as `target`.
Marko Mikulicic 0:c0ecb8bf28eb 6292 */
Marko Mikulicic 0:c0ecb8bf28eb 6293 v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target,
Marko Mikulicic 0:c0ecb8bf28eb 6294 const v7_proxy_hnd_t *handler);
Marko Mikulicic 0:c0ecb8bf28eb 6295
Marko Mikulicic 0:c0ecb8bf28eb 6296 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 6297
Marko Mikulicic 0:c0ecb8bf28eb 6298 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6299 }
Marko Mikulicic 0:c0ecb8bf28eb 6300 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6301
Marko Mikulicic 0:c0ecb8bf28eb 6302 #endif /* CS_V7_SRC_UTIL_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6303 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6304 #line 1 "v7/src/util.h"
Marko Mikulicic 0:c0ecb8bf28eb 6305 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6306 /*
Marko Mikulicic 0:c0ecb8bf28eb 6307 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6308 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6309 */
Marko Mikulicic 0:c0ecb8bf28eb 6310
Marko Mikulicic 0:c0ecb8bf28eb 6311 #ifndef CS_V7_SRC_UTIL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6312 #define CS_V7_SRC_UTIL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6313
Marko Mikulicic 0:c0ecb8bf28eb 6314 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6315 /* Amalgamated: #include "v7/src/util_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6316
Marko Mikulicic 0:c0ecb8bf28eb 6317 struct bcode;
Marko Mikulicic 0:c0ecb8bf28eb 6318
Marko Mikulicic 0:c0ecb8bf28eb 6319 V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6320
Marko Mikulicic 0:c0ecb8bf28eb 6321 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 6322 V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b);
Marko Mikulicic 0:c0ecb8bf28eb 6323 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6324
Marko Mikulicic 0:c0ecb8bf28eb 6325 /*
Marko Mikulicic 0:c0ecb8bf28eb 6326 * At the moment, all other utility functions are public, and are declared in
Marko Mikulicic 0:c0ecb8bf28eb 6327 * `util_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 6328 */
Marko Mikulicic 0:c0ecb8bf28eb 6329
Marko Mikulicic 0:c0ecb8bf28eb 6330 #endif /* CS_V7_SRC_UTIL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6331 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6332 #line 1 "v7/src/shdata.h"
Marko Mikulicic 0:c0ecb8bf28eb 6333 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6334 /*
Marko Mikulicic 0:c0ecb8bf28eb 6335 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6336 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6337 */
Marko Mikulicic 0:c0ecb8bf28eb 6338
Marko Mikulicic 0:c0ecb8bf28eb 6339 /*
Marko Mikulicic 0:c0ecb8bf28eb 6340 * shdata (stands for "shared data") is a simple module that allows to have
Marko Mikulicic 0:c0ecb8bf28eb 6341 * reference count for an arbitrary payload data, which will be freed as
Marko Mikulicic 0:c0ecb8bf28eb 6342 * necessary. A poor man's shared_ptr.
Marko Mikulicic 0:c0ecb8bf28eb 6343 */
Marko Mikulicic 0:c0ecb8bf28eb 6344
Marko Mikulicic 0:c0ecb8bf28eb 6345 #ifndef CS_V7_SRC_SHDATA_H_
Marko Mikulicic 0:c0ecb8bf28eb 6346 #define CS_V7_SRC_SHDATA_H_
Marko Mikulicic 0:c0ecb8bf28eb 6347
Marko Mikulicic 0:c0ecb8bf28eb 6348 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6349
Marko Mikulicic 0:c0ecb8bf28eb 6350 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 6351 struct shdata {
Marko Mikulicic 0:c0ecb8bf28eb 6352 /* Reference count */
Marko Mikulicic 0:c0ecb8bf28eb 6353 uint8_t refcnt;
Marko Mikulicic 0:c0ecb8bf28eb 6354
Marko Mikulicic 0:c0ecb8bf28eb 6355 /*
Marko Mikulicic 0:c0ecb8bf28eb 6356 * Note: we'd use `unsigned char payload[];` here, but we can't, since this
Marko Mikulicic 0:c0ecb8bf28eb 6357 * feature was introduced in C99 only
Marko Mikulicic 0:c0ecb8bf28eb 6358 */
Marko Mikulicic 0:c0ecb8bf28eb 6359 };
Marko Mikulicic 0:c0ecb8bf28eb 6360
Marko Mikulicic 0:c0ecb8bf28eb 6361 /*
Marko Mikulicic 0:c0ecb8bf28eb 6362 * Allocate memory chunk of appropriate size, copy given `payload` data there,
Marko Mikulicic 0:c0ecb8bf28eb 6363 * retain (`shdata_retain()`), and return it.
Marko Mikulicic 0:c0ecb8bf28eb 6364 */
Marko Mikulicic 0:c0ecb8bf28eb 6365 V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 6366
Marko Mikulicic 0:c0ecb8bf28eb 6367 V7_PRIVATE struct shdata *shdata_create_from_string(const char *src);
Marko Mikulicic 0:c0ecb8bf28eb 6368
Marko Mikulicic 0:c0ecb8bf28eb 6369 /*
Marko Mikulicic 0:c0ecb8bf28eb 6370 * Increment reference count for the given shared data
Marko Mikulicic 0:c0ecb8bf28eb 6371 */
Marko Mikulicic 0:c0ecb8bf28eb 6372 V7_PRIVATE void shdata_retain(struct shdata *p);
Marko Mikulicic 0:c0ecb8bf28eb 6373
Marko Mikulicic 0:c0ecb8bf28eb 6374 /*
Marko Mikulicic 0:c0ecb8bf28eb 6375 * Decrement reference count for the given shared data
Marko Mikulicic 0:c0ecb8bf28eb 6376 */
Marko Mikulicic 0:c0ecb8bf28eb 6377 V7_PRIVATE void shdata_release(struct shdata *p);
Marko Mikulicic 0:c0ecb8bf28eb 6378
Marko Mikulicic 0:c0ecb8bf28eb 6379 /*
Marko Mikulicic 0:c0ecb8bf28eb 6380 * Get payload data
Marko Mikulicic 0:c0ecb8bf28eb 6381 */
Marko Mikulicic 0:c0ecb8bf28eb 6382 V7_PRIVATE void *shdata_get_payload(struct shdata *p);
Marko Mikulicic 0:c0ecb8bf28eb 6383
Marko Mikulicic 0:c0ecb8bf28eb 6384 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6385 #endif /* CS_V7_SRC_SHDATA_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6386 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6387 #line 1 "v7/src/eval.h"
Marko Mikulicic 0:c0ecb8bf28eb 6388 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6389 /*
Marko Mikulicic 0:c0ecb8bf28eb 6390 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6391 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6392 */
Marko Mikulicic 0:c0ecb8bf28eb 6393
Marko Mikulicic 0:c0ecb8bf28eb 6394 #ifndef CS_V7_SRC_EVAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6395 #define CS_V7_SRC_EVAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6396
Marko Mikulicic 0:c0ecb8bf28eb 6397 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6398 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6399
Marko Mikulicic 0:c0ecb8bf28eb 6400 struct v7_call_frame_base;
Marko Mikulicic 0:c0ecb8bf28eb 6401
Marko Mikulicic 0:c0ecb8bf28eb 6402 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6403 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6404 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6405
Marko Mikulicic 0:c0ecb8bf28eb 6406 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6407 V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 6408 val_t this_object, uint8_t reset_line_no,
Marko Mikulicic 0:c0ecb8bf28eb 6409 val_t *_res);
Marko Mikulicic 0:c0ecb8bf28eb 6410
Marko Mikulicic 0:c0ecb8bf28eb 6411 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6412 V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 6413 v7_val_t args, uint8_t is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 6414 v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6415
Marko Mikulicic 0:c0ecb8bf28eb 6416 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6417 V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 6418 const char *filename, val_t func, val_t args,
Marko Mikulicic 0:c0ecb8bf28eb 6419 val_t this_object, int is_json, int fr,
Marko Mikulicic 0:c0ecb8bf28eb 6420 uint8_t is_constructor, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6421
Marko Mikulicic 0:c0ecb8bf28eb 6422 /*
Marko Mikulicic 0:c0ecb8bf28eb 6423 * Try to find the call frame whose `type_mask` intersects with the given
Marko Mikulicic 0:c0ecb8bf28eb 6424 * `type_mask`.
Marko Mikulicic 0:c0ecb8bf28eb 6425 *
Marko Mikulicic 0:c0ecb8bf28eb 6426 * Start from the top call frame, and go deeper until the matching frame is
Marko Mikulicic 0:c0ecb8bf28eb 6427 * found, or there's no more call frames. If the needed frame was not found,
Marko Mikulicic 0:c0ecb8bf28eb 6428 * returns `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 6429 */
Marko Mikulicic 0:c0ecb8bf28eb 6430 V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 6431 uint8_t type_mask);
Marko Mikulicic 0:c0ecb8bf28eb 6432
Marko Mikulicic 0:c0ecb8bf28eb 6433 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6434 }
Marko Mikulicic 0:c0ecb8bf28eb 6435 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6436
Marko Mikulicic 0:c0ecb8bf28eb 6437 #endif /* CS_V7_SRC_EVAL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6438 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6439 #line 1 "v7/src/compiler.h"
Marko Mikulicic 0:c0ecb8bf28eb 6440 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6441 /*
Marko Mikulicic 0:c0ecb8bf28eb 6442 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6443 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6444 */
Marko Mikulicic 0:c0ecb8bf28eb 6445
Marko Mikulicic 0:c0ecb8bf28eb 6446 #ifndef CS_V7_SRC_COMPILER_H_
Marko Mikulicic 0:c0ecb8bf28eb 6447 #define CS_V7_SRC_COMPILER_H_
Marko Mikulicic 0:c0ecb8bf28eb 6448
Marko Mikulicic 0:c0ecb8bf28eb 6449 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6450 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6451 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6452
Marko Mikulicic 0:c0ecb8bf28eb 6453 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 6454
Marko Mikulicic 0:c0ecb8bf28eb 6455 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6456 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6457 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6458
Marko Mikulicic 0:c0ecb8bf28eb 6459 V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 6460 struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 6461
Marko Mikulicic 0:c0ecb8bf28eb 6462 V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 6463 ast_off_t *ppos, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 6464
Marko Mikulicic 0:c0ecb8bf28eb 6465 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6466 }
Marko Mikulicic 0:c0ecb8bf28eb 6467 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6468
Marko Mikulicic 0:c0ecb8bf28eb 6469 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 6470
Marko Mikulicic 0:c0ecb8bf28eb 6471 #endif /* CS_V7_SRC_COMPILER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6472 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6473 #line 1 "v7/src/cyg_profile.h"
Marko Mikulicic 0:c0ecb8bf28eb 6474 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6475 /*
Marko Mikulicic 0:c0ecb8bf28eb 6476 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6477 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6478 */
Marko Mikulicic 0:c0ecb8bf28eb 6479
Marko Mikulicic 0:c0ecb8bf28eb 6480 #ifndef CS_V7_SRC_CYG_PROFILE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6481 #define CS_V7_SRC_CYG_PROFILE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6482
Marko Mikulicic 0:c0ecb8bf28eb 6483 /*
Marko Mikulicic 0:c0ecb8bf28eb 6484 * This file contains GCC/clang instrumentation callbacks, as well as
Marko Mikulicic 0:c0ecb8bf28eb 6485 * accompanying code. The actual code in these callbacks depends on enabled
Marko Mikulicic 0:c0ecb8bf28eb 6486 * features. See cyg_profile.c for some implementation details rationale.
Marko Mikulicic 0:c0ecb8bf28eb 6487 */
Marko Mikulicic 0:c0ecb8bf28eb 6488
Marko Mikulicic 0:c0ecb8bf28eb 6489 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 6490
Marko Mikulicic 0:c0ecb8bf28eb 6491 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 6492
Marko Mikulicic 0:c0ecb8bf28eb 6493 /*
Marko Mikulicic 0:c0ecb8bf28eb 6494 * Stack-tracking functionality:
Marko Mikulicic 0:c0ecb8bf28eb 6495 *
Marko Mikulicic 0:c0ecb8bf28eb 6496 * The idea is that the caller should allocate `struct stack_track_ctx`
Marko Mikulicic 0:c0ecb8bf28eb 6497 * (typically on stack) in the function to track the stack usage of, and call
Marko Mikulicic 0:c0ecb8bf28eb 6498 * `v7_stack_track_start()` in the beginning.
Marko Mikulicic 0:c0ecb8bf28eb 6499 *
Marko Mikulicic 0:c0ecb8bf28eb 6500 * Before quitting current stack frame (for example, before returning from
Marko Mikulicic 0:c0ecb8bf28eb 6501 * function), call `v7_stack_track_end()`, which returns the maximum stack
Marko Mikulicic 0:c0ecb8bf28eb 6502 * consumed size.
Marko Mikulicic 0:c0ecb8bf28eb 6503 *
Marko Mikulicic 0:c0ecb8bf28eb 6504 * These calls can be nested: for example, we may track the stack usage of the
Marko Mikulicic 0:c0ecb8bf28eb 6505 * whole application by using these functions in `main()`, as well as track
Marko Mikulicic 0:c0ecb8bf28eb 6506 * stack usage of any nested functions.
Marko Mikulicic 0:c0ecb8bf28eb 6507 *
Marko Mikulicic 0:c0ecb8bf28eb 6508 * Just to stress: both `v7_stack_track_start()` / `v7_stack_track_end()`
Marko Mikulicic 0:c0ecb8bf28eb 6509 * should be called for the same instance of `struct stack_track_ctx` in the
Marko Mikulicic 0:c0ecb8bf28eb 6510 * same stack frame.
Marko Mikulicic 0:c0ecb8bf28eb 6511 */
Marko Mikulicic 0:c0ecb8bf28eb 6512
Marko Mikulicic 0:c0ecb8bf28eb 6513 /* stack tracking context */
Marko Mikulicic 0:c0ecb8bf28eb 6514 struct stack_track_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 6515 struct stack_track_ctx *next;
Marko Mikulicic 0:c0ecb8bf28eb 6516 void *start;
Marko Mikulicic 0:c0ecb8bf28eb 6517 void *max;
Marko Mikulicic 0:c0ecb8bf28eb 6518 };
Marko Mikulicic 0:c0ecb8bf28eb 6519
Marko Mikulicic 0:c0ecb8bf28eb 6520 /* see explanation above */
Marko Mikulicic 0:c0ecb8bf28eb 6521 void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 6522 /* see explanation above */
Marko Mikulicic 0:c0ecb8bf28eb 6523 int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 6524
Marko Mikulicic 0:c0ecb8bf28eb 6525 void v7_stack_stat_clean(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6526
Marko Mikulicic 0:c0ecb8bf28eb 6527 #endif /* V7_ENABLE_STACK_TRACKING */
Marko Mikulicic 0:c0ecb8bf28eb 6528
Marko Mikulicic 0:c0ecb8bf28eb 6529 #endif /* CS_V7_SRC_CYG_PROFILE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6530 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6531 #line 1 "v7/builtin/builtin.h"
Marko Mikulicic 0:c0ecb8bf28eb 6532 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6533 /*
Marko Mikulicic 0:c0ecb8bf28eb 6534 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6535 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6536 */
Marko Mikulicic 0:c0ecb8bf28eb 6537
Marko Mikulicic 0:c0ecb8bf28eb 6538 /*
Marko Mikulicic 0:c0ecb8bf28eb 6539 * === Non-Standard API
Marko Mikulicic 0:c0ecb8bf28eb 6540 *
Marko Mikulicic 0:c0ecb8bf28eb 6541 * V7 has several non-standard extensions for `String.prototype` in
Marko Mikulicic 0:c0ecb8bf28eb 6542 * order to give a compact and fast API to access raw data obtained from
Marko Mikulicic 0:c0ecb8bf28eb 6543 * File, Socket, and hardware input/output such as I2C.
Marko Mikulicic 0:c0ecb8bf28eb 6544 * V7 IO API functions return
Marko Mikulicic 0:c0ecb8bf28eb 6545 * string data as a result of read operations, and that string data is a
Marko Mikulicic 0:c0ecb8bf28eb 6546 * raw byte array. ECMA6 provides `ArrayBuffer` and `DataView` API for dealing
Marko Mikulicic 0:c0ecb8bf28eb 6547 * with raw bytes, because strings in JavaScript are Unicode. That standard
Marko Mikulicic 0:c0ecb8bf28eb 6548 * API is too bloated for the embedded use, and does not allow to use handy
Marko Mikulicic 0:c0ecb8bf28eb 6549 * String API (e.g. `.match()`) against data.
Marko Mikulicic 0:c0ecb8bf28eb 6550 *
Marko Mikulicic 0:c0ecb8bf28eb 6551 * V7 internally stores strings as byte arrays. All strings created by the
Marko Mikulicic 0:c0ecb8bf28eb 6552 * String API are UTF8 encoded. Strings that are the result of
Marko Mikulicic 0:c0ecb8bf28eb 6553 * input/output API calls might not be a valid UTF8 strings, but nevertheless
Marko Mikulicic 0:c0ecb8bf28eb 6554 * they are represented as strings, and the following API allows to access
Marko Mikulicic 0:c0ecb8bf28eb 6555 * underlying byte sequence:
Marko Mikulicic 0:c0ecb8bf28eb 6556 *
Marko Mikulicic 0:c0ecb8bf28eb 6557 * ==== String.prototype.at(position) -> number or NaN
Marko Mikulicic 0:c0ecb8bf28eb 6558 * Return byte at index
Marko Mikulicic 0:c0ecb8bf28eb 6559 * `position`. Byte value is in 0,255 range. If `position` is out of bounds
Marko Mikulicic 0:c0ecb8bf28eb 6560 * (either negative or larger then the byte array length), NaN is returned.
Marko Mikulicic 0:c0ecb8bf28eb 6561 * Example: `"ы".at(0)` returns 0xd1.
Marko Mikulicic 0:c0ecb8bf28eb 6562 *
Marko Mikulicic 0:c0ecb8bf28eb 6563 * ==== String.prototype.blen -> number
Marko Mikulicic 0:c0ecb8bf28eb 6564 * Return string length in bytes.
Marko Mikulicic 0:c0ecb8bf28eb 6565 * Example: `"ы".blen` returns 2. Note that `"ы".length` is 1, since that
Marko Mikulicic 0:c0ecb8bf28eb 6566 * string consists of a single Unicode character (2-byte).
Marko Mikulicic 0:c0ecb8bf28eb 6567 *
Marko Mikulicic 0:c0ecb8bf28eb 6568 * === Builtin API
Marko Mikulicic 0:c0ecb8bf28eb 6569 *
Marko Mikulicic 0:c0ecb8bf28eb 6570 * Builtin API provides additional JavaScript interfaces available for V7
Marko Mikulicic 0:c0ecb8bf28eb 6571 * scripts.
Marko Mikulicic 0:c0ecb8bf28eb 6572 * File API is a wrapper around standard C calls `fopen()`, `fclose()`,
Marko Mikulicic 0:c0ecb8bf28eb 6573 * `fread()`, `fwrite()`, `rename()`, `remove()`.
Marko Mikulicic 0:c0ecb8bf28eb 6574 * Crypto API provides functions for base64, md5, and sha1 encoding/decoding.
Marko Mikulicic 0:c0ecb8bf28eb 6575 * Socket API provides low-level socket API.
Marko Mikulicic 0:c0ecb8bf28eb 6576 *
Marko Mikulicic 0:c0ecb8bf28eb 6577 * ==== File.eval(file_name)
Marko Mikulicic 0:c0ecb8bf28eb 6578 * Parse and run `file_name`.
Marko Mikulicic 0:c0ecb8bf28eb 6579 * Throws an exception if the file doesn't exist, cannot be parsed or if the
Marko Mikulicic 0:c0ecb8bf28eb 6580 * script throws any exception.
Marko Mikulicic 0:c0ecb8bf28eb 6581 *
Marko Mikulicic 0:c0ecb8bf28eb 6582 * ==== File.read(file_name) -> string or undefined
Marko Mikulicic 0:c0ecb8bf28eb 6583 * Read file `file_name` and return a string with a file content.
Marko Mikulicic 0:c0ecb8bf28eb 6584 * On any error, return `undefined` as a result.
Marko Mikulicic 0:c0ecb8bf28eb 6585 *
Marko Mikulicic 0:c0ecb8bf28eb 6586 * ==== File.write(file_name, str) -> true or false
Marko Mikulicic 0:c0ecb8bf28eb 6587 * Write string `str` to a file `file_name`. Return `true` on success,
Marko Mikulicic 0:c0ecb8bf28eb 6588 * `false` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6589 *
Marko Mikulicic 0:c0ecb8bf28eb 6590 * ==== File.open(file_name [, mode]) -> file_object or null
Marko Mikulicic 0:c0ecb8bf28eb 6591 * Open a file `path`. For
Marko Mikulicic 0:c0ecb8bf28eb 6592 * list of valid `mode` values, see `fopen()` documentation. If `mode` is
Marko Mikulicic 0:c0ecb8bf28eb 6593 * not specified, mode `rb` is used, i.e. file is opened in read-only mode.
Marko Mikulicic 0:c0ecb8bf28eb 6594 * Return an opened file object, or null on error. Example:
Marko Mikulicic 0:c0ecb8bf28eb 6595 * `var f = File.open('/etc/passwd'); f.close();`
Marko Mikulicic 0:c0ecb8bf28eb 6596 *
Marko Mikulicic 0:c0ecb8bf28eb 6597 * ==== file_obj.close() -> undefined
Marko Mikulicic 0:c0ecb8bf28eb 6598 * Close opened file object.
Marko Mikulicic 0:c0ecb8bf28eb 6599 * NOTE: it is user's responsibility to close all opened file streams. V7
Marko Mikulicic 0:c0ecb8bf28eb 6600 * does not do that automatically.
Marko Mikulicic 0:c0ecb8bf28eb 6601 *
Marko Mikulicic 0:c0ecb8bf28eb 6602 * ==== file_obj.read() -> string
Marko Mikulicic 0:c0ecb8bf28eb 6603 * Read portion of data from
Marko Mikulicic 0:c0ecb8bf28eb 6604 * an opened file stream. Return string with data, or empty string on EOF
Marko Mikulicic 0:c0ecb8bf28eb 6605 * or error.
Marko Mikulicic 0:c0ecb8bf28eb 6606 *
Marko Mikulicic 0:c0ecb8bf28eb 6607 * ==== file_obj.write(str) -> num_bytes_written
Marko Mikulicic 0:c0ecb8bf28eb 6608 * Write string `str` to the opened file object. Return number of bytes written.
Marko Mikulicic 0:c0ecb8bf28eb 6609 *
Marko Mikulicic 0:c0ecb8bf28eb 6610 * ==== File.rename(old_name, new_name) -> errno
Marko Mikulicic 0:c0ecb8bf28eb 6611 * Rename file `old_name` to
Marko Mikulicic 0:c0ecb8bf28eb 6612 * `new_name`. Return 0 on success, or `errno` value on error.
Marko Mikulicic 0:c0ecb8bf28eb 6613 *
Marko Mikulicic 0:c0ecb8bf28eb 6614 * ==== File.list(dir_name) -> array_of_names
Marko Mikulicic 0:c0ecb8bf28eb 6615 * Return a list of files in a given directory, or `undefined` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6616 *
Marko Mikulicic 0:c0ecb8bf28eb 6617 * ==== File.remove(file_name) -> errno
Marko Mikulicic 0:c0ecb8bf28eb 6618 * Delete file `file_name`.
Marko Mikulicic 0:c0ecb8bf28eb 6619 * Return 0 on success, or `errno` value on error.
Marko Mikulicic 0:c0ecb8bf28eb 6620 *
Marko Mikulicic 0:c0ecb8bf28eb 6621 * ==== Crypto.base64_encode(str)
Marko Mikulicic 0:c0ecb8bf28eb 6622 * Base64-encode input string `str` and return encoded string.
Marko Mikulicic 0:c0ecb8bf28eb 6623 *
Marko Mikulicic 0:c0ecb8bf28eb 6624 * ==== Crypto.base64_decode(str)
Marko Mikulicic 0:c0ecb8bf28eb 6625 * Base64-decode input string `str` and return decoded string.
Marko Mikulicic 0:c0ecb8bf28eb 6626 *
Marko Mikulicic 0:c0ecb8bf28eb 6627 * ==== Crypto.md5(str), Crypto.md5_hex(str)
Marko Mikulicic 0:c0ecb8bf28eb 6628 * Generate MD5 hash from input string `str`. Return 16-byte hash (`md5()`),
Marko Mikulicic 0:c0ecb8bf28eb 6629 * or stringified hexadecimal representation of the hash (`md5_hex`).
Marko Mikulicic 0:c0ecb8bf28eb 6630 *
Marko Mikulicic 0:c0ecb8bf28eb 6631 * ==== Crypto.sha1(str), Crypto.sha1_hex(str)
Marko Mikulicic 0:c0ecb8bf28eb 6632 * Generate SHA1 hash from input string `str`. Return 20-byte hash (`sha1()`),
Marko Mikulicic 0:c0ecb8bf28eb 6633 * or stringified hexadecimal representation of the hash (`sha1_hex`).
Marko Mikulicic 0:c0ecb8bf28eb 6634 *
Marko Mikulicic 0:c0ecb8bf28eb 6635 * ==== Socket.connect(host, port [, is_udp]) -> socket_obj
Marko Mikulicic 0:c0ecb8bf28eb 6636 * Connect to a given host. `host` can be a string IP address, or a host name.
Marko Mikulicic 0:c0ecb8bf28eb 6637 * Optional `is_udp` parameter, if true, indicates that socket should be UDP.
Marko Mikulicic 0:c0ecb8bf28eb 6638 * Return socket object on success, null on error.
Marko Mikulicic 0:c0ecb8bf28eb 6639 *
Marko Mikulicic 0:c0ecb8bf28eb 6640 * ==== Socket.listen(port [, ip_address [,is_udp]]) -> socket_obj
Marko Mikulicic 0:c0ecb8bf28eb 6641 * Create a listening socket on a given port. Optional `ip_address` argument
Marko Mikulicic 0:c0ecb8bf28eb 6642 * specifies and IP address to bind to. Optional `is_udp` parameter, if true,
Marko Mikulicic 0:c0ecb8bf28eb 6643 * indicates that socket should be UDP. Return socket object on success,
Marko Mikulicic 0:c0ecb8bf28eb 6644 * null on error.
Marko Mikulicic 0:c0ecb8bf28eb 6645 *
Marko Mikulicic 0:c0ecb8bf28eb 6646 * ==== socket_obj.accept() -> socket_obj
Marko Mikulicic 0:c0ecb8bf28eb 6647 * Sleep until new incoming connection is arrived. Return accepted socket
Marko Mikulicic 0:c0ecb8bf28eb 6648 * object on success, or `null` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6649 *
Marko Mikulicic 0:c0ecb8bf28eb 6650 * ==== socket_obj.close() -> numeric_errno
Marko Mikulicic 0:c0ecb8bf28eb 6651 * Close socket object. Return 0 on success, or system errno on error.
Marko Mikulicic 0:c0ecb8bf28eb 6652 *
Marko Mikulicic 0:c0ecb8bf28eb 6653 * ==== socket_obj.recv() -> string
Marko Mikulicic 0:c0ecb8bf28eb 6654 * Read data from socket. Return data string, or empty string if peer has
Marko Mikulicic 0:c0ecb8bf28eb 6655 * disconnected, or `null` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6656 *
Marko Mikulicic 0:c0ecb8bf28eb 6657 * ==== socket_obj.recvAll() -> string
Marko Mikulicic 0:c0ecb8bf28eb 6658 * Same as `recv()`, but keeps reading data until socket is closed.
Marko Mikulicic 0:c0ecb8bf28eb 6659 *
Marko Mikulicic 0:c0ecb8bf28eb 6660 * ==== sock.send(string) -> num_bytes_sent
Marko Mikulicic 0:c0ecb8bf28eb 6661 * Send string to the socket. Return number of bytes sent, or 0 on error.
Marko Mikulicic 0:c0ecb8bf28eb 6662 * Simple HTTP client example:
Marko Mikulicic 0:c0ecb8bf28eb 6663 *
Marko Mikulicic 0:c0ecb8bf28eb 6664 * var s = Socket.connect("google.com", 80);
Marko Mikulicic 0:c0ecb8bf28eb 6665 * s.send("GET / HTTP/1.0\n\n");
Marko Mikulicic 0:c0ecb8bf28eb 6666 * var reply = s.recv();
Marko Mikulicic 0:c0ecb8bf28eb 6667 */
Marko Mikulicic 0:c0ecb8bf28eb 6668
Marko Mikulicic 0:c0ecb8bf28eb 6669 #ifndef CS_V7_BUILTIN_BUILTIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6670 #define CS_V7_BUILTIN_BUILTIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6671
Marko Mikulicic 0:c0ecb8bf28eb 6672 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 6673
Marko Mikulicic 0:c0ecb8bf28eb 6674 void init_file(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 6675 void init_socket(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 6676 void init_crypto(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 6677
Marko Mikulicic 0:c0ecb8bf28eb 6678 #endif /* CS_V7_BUILTIN_BUILTIN_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6679 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6680 #line 1 "v7/src/slre.h"
Marko Mikulicic 0:c0ecb8bf28eb 6681 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6682 /*
Marko Mikulicic 0:c0ecb8bf28eb 6683 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6684 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6685 *
Marko Mikulicic 0:c0ecb8bf28eb 6686 * This software is dual-licensed: you can redistribute it and/or modify
Marko Mikulicic 0:c0ecb8bf28eb 6687 * it under the terms of the GNU General Public License version 2 as
Marko Mikulicic 0:c0ecb8bf28eb 6688 * published by the Free Software Foundation. For the terms of this
Marko Mikulicic 0:c0ecb8bf28eb 6689 * license, see <http://www.gnu.org/licenses/>.
Marko Mikulicic 0:c0ecb8bf28eb 6690 *
Marko Mikulicic 0:c0ecb8bf28eb 6691 * You are free to use this software under the terms of the GNU General
Marko Mikulicic 0:c0ecb8bf28eb 6692 * Public License, but WITHOUT ANY WARRANTY; without even the implied
Marko Mikulicic 0:c0ecb8bf28eb 6693 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 6694 * See the GNU General Public License for more details.
Marko Mikulicic 0:c0ecb8bf28eb 6695 *
Marko Mikulicic 0:c0ecb8bf28eb 6696 * Alternatively, you can license this software under a commercial
Marko Mikulicic 0:c0ecb8bf28eb 6697 * license, as set out in <https://www.cesanta.com/license>.
Marko Mikulicic 0:c0ecb8bf28eb 6698 */
Marko Mikulicic 0:c0ecb8bf28eb 6699
Marko Mikulicic 0:c0ecb8bf28eb 6700 #ifndef CS_V7_SRC_SLRE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6701 #define CS_V7_SRC_SLRE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6702
Marko Mikulicic 0:c0ecb8bf28eb 6703 /* Return codes for slre_compile() */
Marko Mikulicic 0:c0ecb8bf28eb 6704 enum slre_error {
Marko Mikulicic 0:c0ecb8bf28eb 6705 SLRE_OK,
Marko Mikulicic 0:c0ecb8bf28eb 6706 SLRE_INVALID_DEC_DIGIT,
Marko Mikulicic 0:c0ecb8bf28eb 6707 SLRE_INVALID_HEX_DIGIT,
Marko Mikulicic 0:c0ecb8bf28eb 6708 SLRE_INVALID_ESC_CHAR,
Marko Mikulicic 0:c0ecb8bf28eb 6709 SLRE_UNTERM_ESC_SEQ,
Marko Mikulicic 0:c0ecb8bf28eb 6710 SLRE_SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 6711 SLRE_UNMATCH_LBR,
Marko Mikulicic 0:c0ecb8bf28eb 6712 SLRE_UNMATCH_RBR,
Marko Mikulicic 0:c0ecb8bf28eb 6713 SLRE_NUM_OVERFLOW,
Marko Mikulicic 0:c0ecb8bf28eb 6714 SLRE_INF_LOOP_M_EMP_STR,
Marko Mikulicic 0:c0ecb8bf28eb 6715 SLRE_TOO_MANY_CHARSETS,
Marko Mikulicic 0:c0ecb8bf28eb 6716 SLRE_INV_CHARSET_RANGE,
Marko Mikulicic 0:c0ecb8bf28eb 6717 SLRE_CHARSET_TOO_LARGE,
Marko Mikulicic 0:c0ecb8bf28eb 6718 SLRE_MALFORMED_CHARSET,
Marko Mikulicic 0:c0ecb8bf28eb 6719 SLRE_INVALID_BACK_REFERENCE,
Marko Mikulicic 0:c0ecb8bf28eb 6720 SLRE_TOO_MANY_CAPTURES,
Marko Mikulicic 0:c0ecb8bf28eb 6721 SLRE_INVALID_QUANTIFIER,
Marko Mikulicic 0:c0ecb8bf28eb 6722 SLRE_BAD_CHAR_AFTER_USD
Marko Mikulicic 0:c0ecb8bf28eb 6723 };
Marko Mikulicic 0:c0ecb8bf28eb 6724
Marko Mikulicic 0:c0ecb8bf28eb 6725 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 6726
Marko Mikulicic 0:c0ecb8bf28eb 6727 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 6728 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6729 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6730
Marko Mikulicic 0:c0ecb8bf28eb 6731 /* Regex flags */
Marko Mikulicic 0:c0ecb8bf28eb 6732 #define SLRE_FLAG_G 1 /* Global - match in the whole string */
Marko Mikulicic 0:c0ecb8bf28eb 6733 #define SLRE_FLAG_I 2 /* Ignore case */
Marko Mikulicic 0:c0ecb8bf28eb 6734 #define SLRE_FLAG_M 4 /* Multiline */
Marko Mikulicic 0:c0ecb8bf28eb 6735 #define SLRE_FLAG_RE 8 /* flag RegExp/String */
Marko Mikulicic 0:c0ecb8bf28eb 6736
Marko Mikulicic 0:c0ecb8bf28eb 6737 /* Describes single capture */
Marko Mikulicic 0:c0ecb8bf28eb 6738 struct slre_cap {
Marko Mikulicic 0:c0ecb8bf28eb 6739 const char *start; /* points to the beginning of the capture group */
Marko Mikulicic 0:c0ecb8bf28eb 6740 const char *end; /* points to the end of the capture group */
Marko Mikulicic 0:c0ecb8bf28eb 6741 };
Marko Mikulicic 0:c0ecb8bf28eb 6742
Marko Mikulicic 0:c0ecb8bf28eb 6743 /* Describes all captures */
Marko Mikulicic 0:c0ecb8bf28eb 6744 #define SLRE_MAX_CAPS 32
Marko Mikulicic 0:c0ecb8bf28eb 6745 struct slre_loot {
Marko Mikulicic 0:c0ecb8bf28eb 6746 int num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 6747 struct slre_cap caps[SLRE_MAX_CAPS];
Marko Mikulicic 0:c0ecb8bf28eb 6748 };
Marko Mikulicic 0:c0ecb8bf28eb 6749
Marko Mikulicic 0:c0ecb8bf28eb 6750 /* Opaque structure that holds compiled regular expression */
Marko Mikulicic 0:c0ecb8bf28eb 6751 struct slre_prog;
Marko Mikulicic 0:c0ecb8bf28eb 6752
Marko Mikulicic 0:c0ecb8bf28eb 6753 int slre_compile(const char *regexp, size_t regexp_len, const char *flags,
Marko Mikulicic 0:c0ecb8bf28eb 6754 size_t flags_len, struct slre_prog **, int is_regex);
Marko Mikulicic 0:c0ecb8bf28eb 6755 int slre_exec(struct slre_prog *prog, int flag_g, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 6756 const char *end, struct slre_loot *loot);
Marko Mikulicic 0:c0ecb8bf28eb 6757 void slre_free(struct slre_prog *prog);
Marko Mikulicic 0:c0ecb8bf28eb 6758
Marko Mikulicic 0:c0ecb8bf28eb 6759 int slre_match(const char *, size_t, const char *, size_t, const char *, size_t,
Marko Mikulicic 0:c0ecb8bf28eb 6760 struct slre_loot *);
Marko Mikulicic 0:c0ecb8bf28eb 6761 int slre_replace(struct slre_loot *loot, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 6762 const char *replace, size_t rep_len, struct slre_loot *dst);
Marko Mikulicic 0:c0ecb8bf28eb 6763 int slre_get_flags(struct slre_prog *);
Marko Mikulicic 0:c0ecb8bf28eb 6764
Marko Mikulicic 0:c0ecb8bf28eb 6765 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 6766 }
Marko Mikulicic 0:c0ecb8bf28eb 6767 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6768
Marko Mikulicic 0:c0ecb8bf28eb 6769 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 6770
Marko Mikulicic 0:c0ecb8bf28eb 6771 #endif /* CS_V7_SRC_SLRE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6772 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6773 #line 1 "v7/src/stdlib.h"
Marko Mikulicic 0:c0ecb8bf28eb 6774 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6775 /*
Marko Mikulicic 0:c0ecb8bf28eb 6776 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6777 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6778 */
Marko Mikulicic 0:c0ecb8bf28eb 6779
Marko Mikulicic 0:c0ecb8bf28eb 6780 #ifndef CS_V7_SRC_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 6781 #define CS_V7_SRC_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 6782
Marko Mikulicic 0:c0ecb8bf28eb 6783 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6784 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6785
Marko Mikulicic 0:c0ecb8bf28eb 6786 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6787 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6788 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6789
Marko Mikulicic 0:c0ecb8bf28eb 6790 /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6791
Marko Mikulicic 0:c0ecb8bf28eb 6792 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6793 V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 6794 int is_json, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6795
Marko Mikulicic 0:c0ecb8bf28eb 6796 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6797 }
Marko Mikulicic 0:c0ecb8bf28eb 6798 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6799
Marko Mikulicic 0:c0ecb8bf28eb 6800 #endif /* CS_V7_SRC_STDLIB_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6801 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6802 #line 1 "v7/src/heapusage.h"
Marko Mikulicic 0:c0ecb8bf28eb 6803 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6804 /*
Marko Mikulicic 0:c0ecb8bf28eb 6805 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6806 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6807 */
Marko Mikulicic 0:c0ecb8bf28eb 6808
Marko Mikulicic 0:c0ecb8bf28eb 6809 #ifndef CS_V7_SRC_HEAPUSAGE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6810 #define CS_V7_SRC_HEAPUSAGE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6811
Marko Mikulicic 0:c0ecb8bf28eb 6812 #if defined(V7_HEAPUSAGE_ENABLE)
Marko Mikulicic 0:c0ecb8bf28eb 6813
Marko Mikulicic 0:c0ecb8bf28eb 6814 extern volatile int heap_dont_count;
Marko Mikulicic 0:c0ecb8bf28eb 6815
Marko Mikulicic 0:c0ecb8bf28eb 6816 /*
Marko Mikulicic 0:c0ecb8bf28eb 6817 * Returns total heap-allocated size in bytes (without any overhead of the
Marko Mikulicic 0:c0ecb8bf28eb 6818 * heap implementation)
Marko Mikulicic 0:c0ecb8bf28eb 6819 */
Marko Mikulicic 0:c0ecb8bf28eb 6820 size_t heapusage_alloc_size(void);
Marko Mikulicic 0:c0ecb8bf28eb 6821
Marko Mikulicic 0:c0ecb8bf28eb 6822 /*
Marko Mikulicic 0:c0ecb8bf28eb 6823 * Returns number of active allocations
Marko Mikulicic 0:c0ecb8bf28eb 6824 */
Marko Mikulicic 0:c0ecb8bf28eb 6825 size_t heapusage_allocs_cnt(void);
Marko Mikulicic 0:c0ecb8bf28eb 6826
Marko Mikulicic 0:c0ecb8bf28eb 6827 /*
Marko Mikulicic 0:c0ecb8bf28eb 6828 * Must be called before allocating some memory that should not be indicated as
Marko Mikulicic 0:c0ecb8bf28eb 6829 * memory consumed for some particular operation: for example, when we
Marko Mikulicic 0:c0ecb8bf28eb 6830 * preallocate some GC buffer.
Marko Mikulicic 0:c0ecb8bf28eb 6831 */
Marko Mikulicic 0:c0ecb8bf28eb 6832 #define heapusage_dont_count(a) \
Marko Mikulicic 0:c0ecb8bf28eb 6833 do { \
Marko Mikulicic 0:c0ecb8bf28eb 6834 heap_dont_count = a; \
Marko Mikulicic 0:c0ecb8bf28eb 6835 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 6836
Marko Mikulicic 0:c0ecb8bf28eb 6837 #else /* V7_HEAPUSAGE_ENABLE */
Marko Mikulicic 0:c0ecb8bf28eb 6838
Marko Mikulicic 0:c0ecb8bf28eb 6839 #define heapusage_alloc_size() (0)
Marko Mikulicic 0:c0ecb8bf28eb 6840 #define heapusage_allocs_cnt() (0)
Marko Mikulicic 0:c0ecb8bf28eb 6841 #define heapusage_dont_count(a)
Marko Mikulicic 0:c0ecb8bf28eb 6842
Marko Mikulicic 0:c0ecb8bf28eb 6843 #endif /* V7_HEAPUSAGE_ENABLE */
Marko Mikulicic 0:c0ecb8bf28eb 6844
Marko Mikulicic 0:c0ecb8bf28eb 6845 #endif /* CS_V7_SRC_HEAPUSAGE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6846 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6847 #line 1 "v7/src/std_proxy.h"
Marko Mikulicic 0:c0ecb8bf28eb 6848 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6849 /*
Marko Mikulicic 0:c0ecb8bf28eb 6850 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6851 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6852 */
Marko Mikulicic 0:c0ecb8bf28eb 6853
Marko Mikulicic 0:c0ecb8bf28eb 6854 #ifndef CS_V7_SRC_STD_PROXY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6855 #define CS_V7_SRC_STD_PROXY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6856
Marko Mikulicic 0:c0ecb8bf28eb 6857 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6858 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6859
Marko Mikulicic 0:c0ecb8bf28eb 6860 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6861
Marko Mikulicic 0:c0ecb8bf28eb 6862 #define _V7_PROXY_TARGET_NAME "__tgt"
Marko Mikulicic 0:c0ecb8bf28eb 6863 #define _V7_PROXY_HANDLER_NAME "__hnd"
Marko Mikulicic 0:c0ecb8bf28eb 6864
Marko Mikulicic 0:c0ecb8bf28eb 6865 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6866 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6867 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6868
Marko Mikulicic 0:c0ecb8bf28eb 6869 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6870
Marko Mikulicic 0:c0ecb8bf28eb 6871 V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6872
Marko Mikulicic 0:c0ecb8bf28eb 6873 V7_PRIVATE void init_proxy(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6874
Marko Mikulicic 0:c0ecb8bf28eb 6875 /*
Marko Mikulicic 0:c0ecb8bf28eb 6876 * Returns whether the given name is one of the special Proxy names
Marko Mikulicic 0:c0ecb8bf28eb 6877 * (_V7_PROXY_TARGET_NAME or _V7_PROXY_HANDLER_NAME)
Marko Mikulicic 0:c0ecb8bf28eb 6878 */
Marko Mikulicic 0:c0ecb8bf28eb 6879 V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len);
Marko Mikulicic 0:c0ecb8bf28eb 6880
Marko Mikulicic 0:c0ecb8bf28eb 6881 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6882
Marko Mikulicic 0:c0ecb8bf28eb 6883 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6884 }
Marko Mikulicic 0:c0ecb8bf28eb 6885 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6886
Marko Mikulicic 0:c0ecb8bf28eb 6887 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 6888
Marko Mikulicic 0:c0ecb8bf28eb 6889 #endif /* CS_V7_SRC_STD_PROXY_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6890 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6891 #line 1 "v7/src/freeze.h"
Marko Mikulicic 0:c0ecb8bf28eb 6892 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6893 /*
Marko Mikulicic 0:c0ecb8bf28eb 6894 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6895 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6896 */
Marko Mikulicic 0:c0ecb8bf28eb 6897
Marko Mikulicic 0:c0ecb8bf28eb 6898 #ifndef CS_V7_SRC_FREEZE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6899 #define CS_V7_SRC_FREEZE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6900
Marko Mikulicic 0:c0ecb8bf28eb 6901 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 6902
Marko Mikulicic 0:c0ecb8bf28eb 6903 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6904
Marko Mikulicic 0:c0ecb8bf28eb 6905 struct v7_property;
Marko Mikulicic 0:c0ecb8bf28eb 6906
Marko Mikulicic 0:c0ecb8bf28eb 6907 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6908 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6909 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6910
Marko Mikulicic 0:c0ecb8bf28eb 6911 V7_PRIVATE void freeze(struct v7 *v7, char *filename);
Marko Mikulicic 0:c0ecb8bf28eb 6912 V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6913 V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop);
Marko Mikulicic 0:c0ecb8bf28eb 6914
Marko Mikulicic 0:c0ecb8bf28eb 6915 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6916 }
Marko Mikulicic 0:c0ecb8bf28eb 6917 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6918
Marko Mikulicic 0:c0ecb8bf28eb 6919 #endif /* V7_FREEZE */
Marko Mikulicic 0:c0ecb8bf28eb 6920
Marko Mikulicic 0:c0ecb8bf28eb 6921 #endif /* CS_V7_SRC_FREEZE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6922 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6923 #line 1 "v7/src/std_array.h"
Marko Mikulicic 0:c0ecb8bf28eb 6924 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6925 /*
Marko Mikulicic 0:c0ecb8bf28eb 6926 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6927 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6928 */
Marko Mikulicic 0:c0ecb8bf28eb 6929
Marko Mikulicic 0:c0ecb8bf28eb 6930 #ifndef CS_V7_SRC_STD_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6931 #define CS_V7_SRC_STD_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6932
Marko Mikulicic 0:c0ecb8bf28eb 6933 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6934
Marko Mikulicic 0:c0ecb8bf28eb 6935 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6936 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6937 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6938
Marko Mikulicic 0:c0ecb8bf28eb 6939 V7_PRIVATE void init_array(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6940
Marko Mikulicic 0:c0ecb8bf28eb 6941 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6942 }
Marko Mikulicic 0:c0ecb8bf28eb 6943 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6944
Marko Mikulicic 0:c0ecb8bf28eb 6945 #endif /* CS_V7_SRC_STD_ARRAY_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6946 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6947 #line 1 "v7/src/std_boolean.h"
Marko Mikulicic 0:c0ecb8bf28eb 6948 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6949 /*
Marko Mikulicic 0:c0ecb8bf28eb 6950 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6951 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6952 */
Marko Mikulicic 0:c0ecb8bf28eb 6953
Marko Mikulicic 0:c0ecb8bf28eb 6954 #ifndef CS_V7_SRC_STD_BOOLEAN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6955 #define CS_V7_SRC_STD_BOOLEAN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6956
Marko Mikulicic 0:c0ecb8bf28eb 6957 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6958
Marko Mikulicic 0:c0ecb8bf28eb 6959 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6960 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6961 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6962
Marko Mikulicic 0:c0ecb8bf28eb 6963 V7_PRIVATE void init_boolean(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6964
Marko Mikulicic 0:c0ecb8bf28eb 6965 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6966 }
Marko Mikulicic 0:c0ecb8bf28eb 6967 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6968
Marko Mikulicic 0:c0ecb8bf28eb 6969 #endif /* CS_V7_SRC_STD_BOOLEAN_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6970 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6971 #line 1 "v7/src/std_date.h"
Marko Mikulicic 0:c0ecb8bf28eb 6972 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6973 /*
Marko Mikulicic 0:c0ecb8bf28eb 6974 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6975 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6976 */
Marko Mikulicic 0:c0ecb8bf28eb 6977
Marko Mikulicic 0:c0ecb8bf28eb 6978 #ifndef CS_V7_SRC_STD_DATE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6979 #define CS_V7_SRC_STD_DATE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6980
Marko Mikulicic 0:c0ecb8bf28eb 6981 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6982
Marko Mikulicic 0:c0ecb8bf28eb 6983 #if V7_ENABLE__Date
Marko Mikulicic 0:c0ecb8bf28eb 6984
Marko Mikulicic 0:c0ecb8bf28eb 6985 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6986 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6987 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6988
Marko Mikulicic 0:c0ecb8bf28eb 6989 V7_PRIVATE void init_date(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6990
Marko Mikulicic 0:c0ecb8bf28eb 6991 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6992 }
Marko Mikulicic 0:c0ecb8bf28eb 6993 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6994
Marko Mikulicic 0:c0ecb8bf28eb 6995 #endif /* V7_ENABLE__Date */
Marko Mikulicic 0:c0ecb8bf28eb 6996 #endif /* CS_V7_SRC_STD_DATE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6997 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6998 #line 1 "v7/src/std_function.h"
Marko Mikulicic 0:c0ecb8bf28eb 6999 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7000 /*
Marko Mikulicic 0:c0ecb8bf28eb 7001 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7002 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7003 */
Marko Mikulicic 0:c0ecb8bf28eb 7004
Marko Mikulicic 0:c0ecb8bf28eb 7005 #ifndef CS_V7_SRC_STD_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 7006 #define CS_V7_SRC_STD_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 7007
Marko Mikulicic 0:c0ecb8bf28eb 7008 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7009
Marko Mikulicic 0:c0ecb8bf28eb 7010 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7011 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7012 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7013
Marko Mikulicic 0:c0ecb8bf28eb 7014 V7_PRIVATE void init_function(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7015
Marko Mikulicic 0:c0ecb8bf28eb 7016 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7017 }
Marko Mikulicic 0:c0ecb8bf28eb 7018 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7019
Marko Mikulicic 0:c0ecb8bf28eb 7020 #endif /* CS_V7_SRC_STD_FUNCTION_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7021 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7022 #line 1 "v7/src/std_json.h"
Marko Mikulicic 0:c0ecb8bf28eb 7023 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7024 /*
Marko Mikulicic 0:c0ecb8bf28eb 7025 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7026 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7027 */
Marko Mikulicic 0:c0ecb8bf28eb 7028
Marko Mikulicic 0:c0ecb8bf28eb 7029 #ifndef CS_V7_SRC_STD_JSON_H_
Marko Mikulicic 0:c0ecb8bf28eb 7030 #define CS_V7_SRC_STD_JSON_H_
Marko Mikulicic 0:c0ecb8bf28eb 7031
Marko Mikulicic 0:c0ecb8bf28eb 7032 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7033
Marko Mikulicic 0:c0ecb8bf28eb 7034 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7035 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7036 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7037
Marko Mikulicic 0:c0ecb8bf28eb 7038 V7_PRIVATE void init_json(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7039
Marko Mikulicic 0:c0ecb8bf28eb 7040 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7041 }
Marko Mikulicic 0:c0ecb8bf28eb 7042 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7043
Marko Mikulicic 0:c0ecb8bf28eb 7044 #endif /* CS_V7_SRC_STD_JSON_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7045 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7046 #line 1 "v7/src/std_math.h"
Marko Mikulicic 0:c0ecb8bf28eb 7047 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7048 /*
Marko Mikulicic 0:c0ecb8bf28eb 7049 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7050 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7051 */
Marko Mikulicic 0:c0ecb8bf28eb 7052
Marko Mikulicic 0:c0ecb8bf28eb 7053 #ifndef CS_V7_SRC_STD_MATH_H_
Marko Mikulicic 0:c0ecb8bf28eb 7054 #define CS_V7_SRC_STD_MATH_H_
Marko Mikulicic 0:c0ecb8bf28eb 7055
Marko Mikulicic 0:c0ecb8bf28eb 7056 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7057
Marko Mikulicic 0:c0ecb8bf28eb 7058 #if V7_ENABLE__Math
Marko Mikulicic 0:c0ecb8bf28eb 7059
Marko Mikulicic 0:c0ecb8bf28eb 7060 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7061 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7062 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7063
Marko Mikulicic 0:c0ecb8bf28eb 7064 V7_PRIVATE void init_math(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7065
Marko Mikulicic 0:c0ecb8bf28eb 7066 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7067 }
Marko Mikulicic 0:c0ecb8bf28eb 7068 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7069
Marko Mikulicic 0:c0ecb8bf28eb 7070 #endif /* V7_ENABLE__Math */
Marko Mikulicic 0:c0ecb8bf28eb 7071 #endif /* CS_V7_SRC_STD_MATH_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7072 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7073 #line 1 "v7/src/std_number.h"
Marko Mikulicic 0:c0ecb8bf28eb 7074 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7075 /*
Marko Mikulicic 0:c0ecb8bf28eb 7076 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7077 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7078 */
Marko Mikulicic 0:c0ecb8bf28eb 7079
Marko Mikulicic 0:c0ecb8bf28eb 7080 #ifndef CS_V7_SRC_STD_NUMBER_H_
Marko Mikulicic 0:c0ecb8bf28eb 7081 #define CS_V7_SRC_STD_NUMBER_H_
Marko Mikulicic 0:c0ecb8bf28eb 7082
Marko Mikulicic 0:c0ecb8bf28eb 7083 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7084
Marko Mikulicic 0:c0ecb8bf28eb 7085 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7086 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7087 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7088
Marko Mikulicic 0:c0ecb8bf28eb 7089 V7_PRIVATE void init_number(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7090
Marko Mikulicic 0:c0ecb8bf28eb 7091 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7092 }
Marko Mikulicic 0:c0ecb8bf28eb 7093 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7094
Marko Mikulicic 0:c0ecb8bf28eb 7095 #endif /* CS_V7_SRC_STD_NUMBER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7096 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7097 #line 1 "v7/src/std_object.h"
Marko Mikulicic 0:c0ecb8bf28eb 7098 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7099 /*
Marko Mikulicic 0:c0ecb8bf28eb 7100 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7101 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7102 */
Marko Mikulicic 0:c0ecb8bf28eb 7103
Marko Mikulicic 0:c0ecb8bf28eb 7104 #ifndef CS_V7_SRC_STD_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 7105 #define CS_V7_SRC_STD_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 7106
Marko Mikulicic 0:c0ecb8bf28eb 7107 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7108 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7109
Marko Mikulicic 0:c0ecb8bf28eb 7110 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 7111
Marko Mikulicic 0:c0ecb8bf28eb 7112 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7113 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7114 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7115
Marko Mikulicic 0:c0ecb8bf28eb 7116 V7_PRIVATE void init_object(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7117
Marko Mikulicic 0:c0ecb8bf28eb 7118 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 7119 V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 7120
Marko Mikulicic 0:c0ecb8bf28eb 7121 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7122 }
Marko Mikulicic 0:c0ecb8bf28eb 7123 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7124
Marko Mikulicic 0:c0ecb8bf28eb 7125 #endif /* CS_V7_SRC_STD_OBJECT_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7126 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7127 #line 1 "v7/src/std_regex.h"
Marko Mikulicic 0:c0ecb8bf28eb 7128 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7129 /*
Marko Mikulicic 0:c0ecb8bf28eb 7130 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7131 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7132 */
Marko Mikulicic 0:c0ecb8bf28eb 7133
Marko Mikulicic 0:c0ecb8bf28eb 7134 #ifndef CS_V7_SRC_STD_REGEX_H_
Marko Mikulicic 0:c0ecb8bf28eb 7135 #define CS_V7_SRC_STD_REGEX_H_
Marko Mikulicic 0:c0ecb8bf28eb 7136
Marko Mikulicic 0:c0ecb8bf28eb 7137 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7138 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7139
Marko Mikulicic 0:c0ecb8bf28eb 7140 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 7141
Marko Mikulicic 0:c0ecb8bf28eb 7142 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7143 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7144 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7145
Marko Mikulicic 0:c0ecb8bf28eb 7146 V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 7147 V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, v7_val_t rx, v7_val_t vstr,
Marko Mikulicic 0:c0ecb8bf28eb 7148 int lind, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 7149
Marko Mikulicic 0:c0ecb8bf28eb 7150 V7_PRIVATE void init_regex(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7151
Marko Mikulicic 0:c0ecb8bf28eb 7152 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7153 }
Marko Mikulicic 0:c0ecb8bf28eb 7154 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7155
Marko Mikulicic 0:c0ecb8bf28eb 7156 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 7157
Marko Mikulicic 0:c0ecb8bf28eb 7158 #endif /* CS_V7_SRC_STD_REGEX_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7159 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7160 #line 1 "v7/src/std_string.h"
Marko Mikulicic 0:c0ecb8bf28eb 7161 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7162 /*
Marko Mikulicic 0:c0ecb8bf28eb 7163 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7164 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7165 */
Marko Mikulicic 0:c0ecb8bf28eb 7166
Marko Mikulicic 0:c0ecb8bf28eb 7167 #ifndef CS_V7_SRC_STD_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 7168 #define CS_V7_SRC_STD_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 7169
Marko Mikulicic 0:c0ecb8bf28eb 7170 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7171 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7172
Marko Mikulicic 0:c0ecb8bf28eb 7173 /* Max captures for String.replace() */
Marko Mikulicic 0:c0ecb8bf28eb 7174 #define V7_RE_MAX_REPL_SUB 20
Marko Mikulicic 0:c0ecb8bf28eb 7175
Marko Mikulicic 0:c0ecb8bf28eb 7176 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7177 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7178 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7179
Marko Mikulicic 0:c0ecb8bf28eb 7180 V7_PRIVATE void init_string(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7181
Marko Mikulicic 0:c0ecb8bf28eb 7182 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7183 }
Marko Mikulicic 0:c0ecb8bf28eb 7184 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7185
Marko Mikulicic 0:c0ecb8bf28eb 7186 #endif /* CS_V7_SRC_STD_STRING_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7187 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7188 #line 1 "v7/src/js_stdlib.h"
Marko Mikulicic 0:c0ecb8bf28eb 7189 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7190 /*
Marko Mikulicic 0:c0ecb8bf28eb 7191 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7192 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7193 */
Marko Mikulicic 0:c0ecb8bf28eb 7194
Marko Mikulicic 0:c0ecb8bf28eb 7195 #ifndef CS_V7_SRC_JS_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 7196 #define CS_V7_SRC_JS_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 7197
Marko Mikulicic 0:c0ecb8bf28eb 7198 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7199
Marko Mikulicic 0:c0ecb8bf28eb 7200 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7201 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7202 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7203
Marko Mikulicic 0:c0ecb8bf28eb 7204 V7_PRIVATE void init_js_stdlib(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 7205
Marko Mikulicic 0:c0ecb8bf28eb 7206 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7207 }
Marko Mikulicic 0:c0ecb8bf28eb 7208 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7209
Marko Mikulicic 0:c0ecb8bf28eb 7210 #endif /* CS_V7_SRC_JS_STDLIB_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7211 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7212 #line 1 "v7/src/main_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 7213 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7214 /*
Marko Mikulicic 0:c0ecb8bf28eb 7215 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7216 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7217 */
Marko Mikulicic 0:c0ecb8bf28eb 7218
Marko Mikulicic 0:c0ecb8bf28eb 7219 /*
Marko Mikulicic 0:c0ecb8bf28eb 7220 * === v7 main()
Marko Mikulicic 0:c0ecb8bf28eb 7221 */
Marko Mikulicic 0:c0ecb8bf28eb 7222
Marko Mikulicic 0:c0ecb8bf28eb 7223 #ifndef CS_V7_SRC_MAIN_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 7224 #define CS_V7_SRC_MAIN_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 7225
Marko Mikulicic 0:c0ecb8bf28eb 7226 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7227
Marko Mikulicic 0:c0ecb8bf28eb 7228 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7229 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7230 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7231
Marko Mikulicic 0:c0ecb8bf28eb 7232 /*
Marko Mikulicic 0:c0ecb8bf28eb 7233 * V7 executable main function.
Marko Mikulicic 0:c0ecb8bf28eb 7234 *
Marko Mikulicic 0:c0ecb8bf28eb 7235 * There are various callbacks available:
Marko Mikulicic 0:c0ecb8bf28eb 7236 *
Marko Mikulicic 0:c0ecb8bf28eb 7237 * `pre_freeze_init()` and `pre_init()` are optional intialization functions,
Marko Mikulicic 0:c0ecb8bf28eb 7238 * aimed to export any extra functionality into vanilla v7 engine. They are
Marko Mikulicic 0:c0ecb8bf28eb 7239 * called after v7 initialization, before executing given files or inline
Marko Mikulicic 0:c0ecb8bf28eb 7240 * expressions. `pre_freeze_init()` is called before "freezing" v7 state;
Marko Mikulicic 0:c0ecb8bf28eb 7241 * whereas `pre_init` called afterwards.
Marko Mikulicic 0:c0ecb8bf28eb 7242 *
Marko Mikulicic 0:c0ecb8bf28eb 7243 * `post_init()`, if provided, is called after executing files and expressions,
Marko Mikulicic 0:c0ecb8bf28eb 7244 * before destroying v7 instance and exiting.
Marko Mikulicic 0:c0ecb8bf28eb 7245 */
Marko Mikulicic 0:c0ecb8bf28eb 7246 int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *),
Marko Mikulicic 0:c0ecb8bf28eb 7247 void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *));
Marko Mikulicic 0:c0ecb8bf28eb 7248
Marko Mikulicic 0:c0ecb8bf28eb 7249 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7250 }
Marko Mikulicic 0:c0ecb8bf28eb 7251 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7252
Marko Mikulicic 0:c0ecb8bf28eb 7253 #endif /* CS_V7_SRC_MAIN_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7254 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7255 #line 1 "v7/src/main.h"
Marko Mikulicic 0:c0ecb8bf28eb 7256 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7257 /*
Marko Mikulicic 0:c0ecb8bf28eb 7258 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7259 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7260 */
Marko Mikulicic 0:c0ecb8bf28eb 7261
Marko Mikulicic 0:c0ecb8bf28eb 7262 #ifndef CS_V7_SRC_MAIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 7263 #define CS_V7_SRC_MAIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 7264
Marko Mikulicic 0:c0ecb8bf28eb 7265 /* Amalgamated: #include "v7/src/main_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7266
Marko Mikulicic 0:c0ecb8bf28eb 7267 #endif /* CS_V7_SRC_MAIN_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7268 #ifndef V7_EXPORT_INTERNAL_HEADERS
Marko Mikulicic 0:c0ecb8bf28eb 7269 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7270 #line 1 "common/mbuf.c"
Marko Mikulicic 0:c0ecb8bf28eb 7271 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7272 /*
Marko Mikulicic 0:c0ecb8bf28eb 7273 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7274 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7275 */
Marko Mikulicic 0:c0ecb8bf28eb 7276
Marko Mikulicic 0:c0ecb8bf28eb 7277 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 7278
Marko Mikulicic 0:c0ecb8bf28eb 7279 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 7280 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 7281 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7282
Marko Mikulicic 0:c0ecb8bf28eb 7283 #ifndef MBUF_REALLOC
Marko Mikulicic 0:c0ecb8bf28eb 7284 #define MBUF_REALLOC realloc
Marko Mikulicic 0:c0ecb8bf28eb 7285 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7286
Marko Mikulicic 0:c0ecb8bf28eb 7287 #ifndef MBUF_FREE
Marko Mikulicic 0:c0ecb8bf28eb 7288 #define MBUF_FREE free
Marko Mikulicic 0:c0ecb8bf28eb 7289 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7290
Marko Mikulicic 0:c0ecb8bf28eb 7291 void mbuf_init(struct mbuf *mbuf, size_t initial_size) {
Marko Mikulicic 0:c0ecb8bf28eb 7292 mbuf->len = mbuf->size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7293 mbuf->buf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7294 mbuf_resize(mbuf, initial_size);
Marko Mikulicic 0:c0ecb8bf28eb 7295 }
Marko Mikulicic 0:c0ecb8bf28eb 7296
Marko Mikulicic 0:c0ecb8bf28eb 7297 void mbuf_free(struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 7298 if (mbuf->buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7299 MBUF_FREE(mbuf->buf);
Marko Mikulicic 0:c0ecb8bf28eb 7300 mbuf_init(mbuf, 0);
Marko Mikulicic 0:c0ecb8bf28eb 7301 }
Marko Mikulicic 0:c0ecb8bf28eb 7302 }
Marko Mikulicic 0:c0ecb8bf28eb 7303
Marko Mikulicic 0:c0ecb8bf28eb 7304 void mbuf_resize(struct mbuf *a, size_t new_size) {
Marko Mikulicic 0:c0ecb8bf28eb 7305 if (new_size > a->size || (new_size < a->size && new_size >= a->len)) {
Marko Mikulicic 0:c0ecb8bf28eb 7306 char *buf = (char *) MBUF_REALLOC(a->buf, new_size);
Marko Mikulicic 0:c0ecb8bf28eb 7307 /*
Marko Mikulicic 0:c0ecb8bf28eb 7308 * In case realloc fails, there's not much we can do, except keep things as
Marko Mikulicic 0:c0ecb8bf28eb 7309 * they are. Note that NULL is a valid return value from realloc when
Marko Mikulicic 0:c0ecb8bf28eb 7310 * size == 0, but that is covered too.
Marko Mikulicic 0:c0ecb8bf28eb 7311 */
Marko Mikulicic 0:c0ecb8bf28eb 7312 if (buf == NULL && new_size != 0) return;
Marko Mikulicic 0:c0ecb8bf28eb 7313 a->buf = buf;
Marko Mikulicic 0:c0ecb8bf28eb 7314 a->size = new_size;
Marko Mikulicic 0:c0ecb8bf28eb 7315 }
Marko Mikulicic 0:c0ecb8bf28eb 7316 }
Marko Mikulicic 0:c0ecb8bf28eb 7317
Marko Mikulicic 0:c0ecb8bf28eb 7318 void mbuf_trim(struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 7319 mbuf_resize(mbuf, mbuf->len);
Marko Mikulicic 0:c0ecb8bf28eb 7320 }
Marko Mikulicic 0:c0ecb8bf28eb 7321
Marko Mikulicic 0:c0ecb8bf28eb 7322 size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 7323 char *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7324
Marko Mikulicic 0:c0ecb8bf28eb 7325 assert(a != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 7326 assert(a->len <= a->size);
Marko Mikulicic 0:c0ecb8bf28eb 7327 assert(off <= a->len);
Marko Mikulicic 0:c0ecb8bf28eb 7328
Marko Mikulicic 0:c0ecb8bf28eb 7329 /* check overflow */
Marko Mikulicic 0:c0ecb8bf28eb 7330 if (~(size_t) 0 - (size_t) a->buf < len) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 7331
Marko Mikulicic 0:c0ecb8bf28eb 7332 if (a->len + len <= a->size) {
Marko Mikulicic 0:c0ecb8bf28eb 7333 memmove(a->buf + off + len, a->buf + off, a->len - off);
Marko Mikulicic 0:c0ecb8bf28eb 7334 if (buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7335 memcpy(a->buf + off, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 7336 }
Marko Mikulicic 0:c0ecb8bf28eb 7337 a->len += len;
Marko Mikulicic 0:c0ecb8bf28eb 7338 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7339 size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER);
Marko Mikulicic 0:c0ecb8bf28eb 7340 if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7341 a->buf = p;
Marko Mikulicic 0:c0ecb8bf28eb 7342 memmove(a->buf + off + len, a->buf + off, a->len - off);
Marko Mikulicic 0:c0ecb8bf28eb 7343 if (buf != NULL) memcpy(a->buf + off, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 7344 a->len += len;
Marko Mikulicic 0:c0ecb8bf28eb 7345 a->size = new_size;
Marko Mikulicic 0:c0ecb8bf28eb 7346 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7347 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7348 }
Marko Mikulicic 0:c0ecb8bf28eb 7349 }
Marko Mikulicic 0:c0ecb8bf28eb 7350
Marko Mikulicic 0:c0ecb8bf28eb 7351 return len;
Marko Mikulicic 0:c0ecb8bf28eb 7352 }
Marko Mikulicic 0:c0ecb8bf28eb 7353
Marko Mikulicic 0:c0ecb8bf28eb 7354 size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 7355 return mbuf_insert(a, a->len, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 7356 }
Marko Mikulicic 0:c0ecb8bf28eb 7357
Marko Mikulicic 0:c0ecb8bf28eb 7358 void mbuf_remove(struct mbuf *mb, size_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 7359 if (n > 0 && n <= mb->len) {
Marko Mikulicic 0:c0ecb8bf28eb 7360 memmove(mb->buf, mb->buf + n, mb->len - n);
Marko Mikulicic 0:c0ecb8bf28eb 7361 mb->len -= n;
Marko Mikulicic 0:c0ecb8bf28eb 7362 }
Marko Mikulicic 0:c0ecb8bf28eb 7363 }
Marko Mikulicic 0:c0ecb8bf28eb 7364
Marko Mikulicic 0:c0ecb8bf28eb 7365 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 7366 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7367 #line 1 "common/str_util.c"
Marko Mikulicic 0:c0ecb8bf28eb 7368 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7369 /*
Marko Mikulicic 0:c0ecb8bf28eb 7370 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7371 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7372 */
Marko Mikulicic 0:c0ecb8bf28eb 7373
Marko Mikulicic 0:c0ecb8bf28eb 7374 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 7375
Marko Mikulicic 0:c0ecb8bf28eb 7376 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7377 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7378
Marko Mikulicic 0:c0ecb8bf28eb 7379 size_t c_strnlen(const char *s, size_t maxlen) {
Marko Mikulicic 0:c0ecb8bf28eb 7380 size_t l = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7381 for (; l < maxlen && s[l] != '\0'; l++) {
Marko Mikulicic 0:c0ecb8bf28eb 7382 }
Marko Mikulicic 0:c0ecb8bf28eb 7383 return l;
Marko Mikulicic 0:c0ecb8bf28eb 7384 }
Marko Mikulicic 0:c0ecb8bf28eb 7385
Marko Mikulicic 0:c0ecb8bf28eb 7386 #define C_SNPRINTF_APPEND_CHAR(ch) \
Marko Mikulicic 0:c0ecb8bf28eb 7387 do { \
Marko Mikulicic 0:c0ecb8bf28eb 7388 if (i < (int) buf_size) buf[i] = ch; \
Marko Mikulicic 0:c0ecb8bf28eb 7389 i++; \
Marko Mikulicic 0:c0ecb8bf28eb 7390 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 7391
Marko Mikulicic 0:c0ecb8bf28eb 7392 #define C_SNPRINTF_FLAG_ZERO 1
Marko Mikulicic 0:c0ecb8bf28eb 7393
Marko Mikulicic 0:c0ecb8bf28eb 7394 #ifdef C_DISABLE_BUILTIN_SNPRINTF
Marko Mikulicic 0:c0ecb8bf28eb 7395 int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) {
Marko Mikulicic 0:c0ecb8bf28eb 7396 return vsnprintf(buf, buf_size, fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 7397 }
Marko Mikulicic 0:c0ecb8bf28eb 7398 #else
Marko Mikulicic 0:c0ecb8bf28eb 7399 static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags,
Marko Mikulicic 0:c0ecb8bf28eb 7400 int field_width) {
Marko Mikulicic 0:c0ecb8bf28eb 7401 char tmp[40];
Marko Mikulicic 0:c0ecb8bf28eb 7402 int i = 0, k = 0, neg = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7403
Marko Mikulicic 0:c0ecb8bf28eb 7404 if (num < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7405 neg++;
Marko Mikulicic 0:c0ecb8bf28eb 7406 num = -num;
Marko Mikulicic 0:c0ecb8bf28eb 7407 }
Marko Mikulicic 0:c0ecb8bf28eb 7408
Marko Mikulicic 0:c0ecb8bf28eb 7409 /* Print into temporary buffer - in reverse order */
Marko Mikulicic 0:c0ecb8bf28eb 7410 do {
Marko Mikulicic 0:c0ecb8bf28eb 7411 int rem = num % base;
Marko Mikulicic 0:c0ecb8bf28eb 7412 if (rem < 10) {
Marko Mikulicic 0:c0ecb8bf28eb 7413 tmp[k++] = '0' + rem;
Marko Mikulicic 0:c0ecb8bf28eb 7414 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7415 tmp[k++] = 'a' + (rem - 10);
Marko Mikulicic 0:c0ecb8bf28eb 7416 }
Marko Mikulicic 0:c0ecb8bf28eb 7417 num /= base;
Marko Mikulicic 0:c0ecb8bf28eb 7418 } while (num > 0);
Marko Mikulicic 0:c0ecb8bf28eb 7419
Marko Mikulicic 0:c0ecb8bf28eb 7420 /* Zero padding */
Marko Mikulicic 0:c0ecb8bf28eb 7421 if (flags && C_SNPRINTF_FLAG_ZERO) {
Marko Mikulicic 0:c0ecb8bf28eb 7422 while (k < field_width && k < (int) sizeof(tmp) - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 7423 tmp[k++] = '0';
Marko Mikulicic 0:c0ecb8bf28eb 7424 }
Marko Mikulicic 0:c0ecb8bf28eb 7425 }
Marko Mikulicic 0:c0ecb8bf28eb 7426
Marko Mikulicic 0:c0ecb8bf28eb 7427 /* And sign */
Marko Mikulicic 0:c0ecb8bf28eb 7428 if (neg) {
Marko Mikulicic 0:c0ecb8bf28eb 7429 tmp[k++] = '-';
Marko Mikulicic 0:c0ecb8bf28eb 7430 }
Marko Mikulicic 0:c0ecb8bf28eb 7431
Marko Mikulicic 0:c0ecb8bf28eb 7432 /* Now output */
Marko Mikulicic 0:c0ecb8bf28eb 7433 while (--k >= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7434 C_SNPRINTF_APPEND_CHAR(tmp[k]);
Marko Mikulicic 0:c0ecb8bf28eb 7435 }
Marko Mikulicic 0:c0ecb8bf28eb 7436
Marko Mikulicic 0:c0ecb8bf28eb 7437 return i;
Marko Mikulicic 0:c0ecb8bf28eb 7438 }
Marko Mikulicic 0:c0ecb8bf28eb 7439
Marko Mikulicic 0:c0ecb8bf28eb 7440 int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) {
Marko Mikulicic 0:c0ecb8bf28eb 7441 int ch, i = 0, len_mod, flags, precision, field_width;
Marko Mikulicic 0:c0ecb8bf28eb 7442
Marko Mikulicic 0:c0ecb8bf28eb 7443 while ((ch = *fmt++) != '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 7444 if (ch != '%') {
Marko Mikulicic 0:c0ecb8bf28eb 7445 C_SNPRINTF_APPEND_CHAR(ch);
Marko Mikulicic 0:c0ecb8bf28eb 7446 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7447 /*
Marko Mikulicic 0:c0ecb8bf28eb 7448 * Conversion specification:
Marko Mikulicic 0:c0ecb8bf28eb 7449 * zero or more flags (one of: # 0 - <space> + ')
Marko Mikulicic 0:c0ecb8bf28eb 7450 * an optional minimum field width (digits)
Marko Mikulicic 0:c0ecb8bf28eb 7451 * an optional precision (. followed by digits, or *)
Marko Mikulicic 0:c0ecb8bf28eb 7452 * an optional length modifier (one of: hh h l ll L q j z t)
Marko Mikulicic 0:c0ecb8bf28eb 7453 * conversion specifier (one of: d i o u x X e E f F g G a A c s p n)
Marko Mikulicic 0:c0ecb8bf28eb 7454 */
Marko Mikulicic 0:c0ecb8bf28eb 7455 flags = field_width = precision = len_mod = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7456
Marko Mikulicic 0:c0ecb8bf28eb 7457 /* Flags. only zero-pad flag is supported. */
Marko Mikulicic 0:c0ecb8bf28eb 7458 if (*fmt == '0') {
Marko Mikulicic 0:c0ecb8bf28eb 7459 flags |= C_SNPRINTF_FLAG_ZERO;
Marko Mikulicic 0:c0ecb8bf28eb 7460 }
Marko Mikulicic 0:c0ecb8bf28eb 7461
Marko Mikulicic 0:c0ecb8bf28eb 7462 /* Field width */
Marko Mikulicic 0:c0ecb8bf28eb 7463 while (*fmt >= '0' && *fmt <= '9') {
Marko Mikulicic 0:c0ecb8bf28eb 7464 field_width *= 10;
Marko Mikulicic 0:c0ecb8bf28eb 7465 field_width += *fmt++ - '0';
Marko Mikulicic 0:c0ecb8bf28eb 7466 }
Marko Mikulicic 0:c0ecb8bf28eb 7467 /* Dynamic field width */
Marko Mikulicic 0:c0ecb8bf28eb 7468 if (*fmt == '*') {
Marko Mikulicic 0:c0ecb8bf28eb 7469 field_width = va_arg(ap, int);
Marko Mikulicic 0:c0ecb8bf28eb 7470 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7471 }
Marko Mikulicic 0:c0ecb8bf28eb 7472
Marko Mikulicic 0:c0ecb8bf28eb 7473 /* Precision */
Marko Mikulicic 0:c0ecb8bf28eb 7474 if (*fmt == '.') {
Marko Mikulicic 0:c0ecb8bf28eb 7475 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7476 if (*fmt == '*') {
Marko Mikulicic 0:c0ecb8bf28eb 7477 precision = va_arg(ap, int);
Marko Mikulicic 0:c0ecb8bf28eb 7478 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7479 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7480 while (*fmt >= '0' && *fmt <= '9') {
Marko Mikulicic 0:c0ecb8bf28eb 7481 precision *= 10;
Marko Mikulicic 0:c0ecb8bf28eb 7482 precision += *fmt++ - '0';
Marko Mikulicic 0:c0ecb8bf28eb 7483 }
Marko Mikulicic 0:c0ecb8bf28eb 7484 }
Marko Mikulicic 0:c0ecb8bf28eb 7485 }
Marko Mikulicic 0:c0ecb8bf28eb 7486
Marko Mikulicic 0:c0ecb8bf28eb 7487 /* Length modifier */
Marko Mikulicic 0:c0ecb8bf28eb 7488 switch (*fmt) {
Marko Mikulicic 0:c0ecb8bf28eb 7489 case 'h':
Marko Mikulicic 0:c0ecb8bf28eb 7490 case 'l':
Marko Mikulicic 0:c0ecb8bf28eb 7491 case 'L':
Marko Mikulicic 0:c0ecb8bf28eb 7492 case 'I':
Marko Mikulicic 0:c0ecb8bf28eb 7493 case 'q':
Marko Mikulicic 0:c0ecb8bf28eb 7494 case 'j':
Marko Mikulicic 0:c0ecb8bf28eb 7495 case 'z':
Marko Mikulicic 0:c0ecb8bf28eb 7496 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 7497 len_mod = *fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7498 if (*fmt == 'h') {
Marko Mikulicic 0:c0ecb8bf28eb 7499 len_mod = 'H';
Marko Mikulicic 0:c0ecb8bf28eb 7500 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7501 }
Marko Mikulicic 0:c0ecb8bf28eb 7502 if (*fmt == 'l') {
Marko Mikulicic 0:c0ecb8bf28eb 7503 len_mod = 'q';
Marko Mikulicic 0:c0ecb8bf28eb 7504 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7505 }
Marko Mikulicic 0:c0ecb8bf28eb 7506 break;
Marko Mikulicic 0:c0ecb8bf28eb 7507 }
Marko Mikulicic 0:c0ecb8bf28eb 7508
Marko Mikulicic 0:c0ecb8bf28eb 7509 ch = *fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7510 if (ch == 's') {
Marko Mikulicic 0:c0ecb8bf28eb 7511 const char *s = va_arg(ap, const char *); /* Always fetch parameter */
Marko Mikulicic 0:c0ecb8bf28eb 7512 int j;
Marko Mikulicic 0:c0ecb8bf28eb 7513 int pad = field_width - (precision >= 0 ? c_strnlen(s, precision) : 0);
Marko Mikulicic 0:c0ecb8bf28eb 7514 for (j = 0; j < pad; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 7515 C_SNPRINTF_APPEND_CHAR(' ');
Marko Mikulicic 0:c0ecb8bf28eb 7516 }
Marko Mikulicic 0:c0ecb8bf28eb 7517
Marko Mikulicic 0:c0ecb8bf28eb 7518 /* `s` may be NULL in case of %.*s */
Marko Mikulicic 0:c0ecb8bf28eb 7519 if (s != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7520 /* Ignore negative and 0 precisions */
Marko Mikulicic 0:c0ecb8bf28eb 7521 for (j = 0; (precision <= 0 || j < precision) && s[j] != '\0'; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 7522 C_SNPRINTF_APPEND_CHAR(s[j]);
Marko Mikulicic 0:c0ecb8bf28eb 7523 }
Marko Mikulicic 0:c0ecb8bf28eb 7524 }
Marko Mikulicic 0:c0ecb8bf28eb 7525 } else if (ch == 'c') {
Marko Mikulicic 0:c0ecb8bf28eb 7526 ch = va_arg(ap, int); /* Always fetch parameter */
Marko Mikulicic 0:c0ecb8bf28eb 7527 C_SNPRINTF_APPEND_CHAR(ch);
Marko Mikulicic 0:c0ecb8bf28eb 7528 } else if (ch == 'd' && len_mod == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7529 i += c_itoa(buf + i, buf_size - i, va_arg(ap, int), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7530 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7531 } else if (ch == 'd' && len_mod == 'l') {
Marko Mikulicic 0:c0ecb8bf28eb 7532 i += c_itoa(buf + i, buf_size - i, va_arg(ap, long), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7533 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7534 #ifdef SSIZE_MAX
Marko Mikulicic 0:c0ecb8bf28eb 7535 } else if (ch == 'd' && len_mod == 'z') {
Marko Mikulicic 0:c0ecb8bf28eb 7536 i += c_itoa(buf + i, buf_size - i, va_arg(ap, ssize_t), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7537 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7538 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7539 } else if (ch == 'd' && len_mod == 'q') {
Marko Mikulicic 0:c0ecb8bf28eb 7540 i += c_itoa(buf + i, buf_size - i, va_arg(ap, int64_t), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7541 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7542 } else if ((ch == 'x' || ch == 'u') && len_mod == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7543 i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned),
Marko Mikulicic 0:c0ecb8bf28eb 7544 ch == 'x' ? 16 : 10, flags, field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7545 } else if ((ch == 'x' || ch == 'u') && len_mod == 'l') {
Marko Mikulicic 0:c0ecb8bf28eb 7546 i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned long),
Marko Mikulicic 0:c0ecb8bf28eb 7547 ch == 'x' ? 16 : 10, flags, field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7548 } else if ((ch == 'x' || ch == 'u') && len_mod == 'z') {
Marko Mikulicic 0:c0ecb8bf28eb 7549 i += c_itoa(buf + i, buf_size - i, va_arg(ap, size_t),
Marko Mikulicic 0:c0ecb8bf28eb 7550 ch == 'x' ? 16 : 10, flags, field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7551 } else if (ch == 'p') {
Marko Mikulicic 0:c0ecb8bf28eb 7552 unsigned long num = (unsigned long) (uintptr_t) va_arg(ap, void *);
Marko Mikulicic 0:c0ecb8bf28eb 7553 C_SNPRINTF_APPEND_CHAR('0');
Marko Mikulicic 0:c0ecb8bf28eb 7554 C_SNPRINTF_APPEND_CHAR('x');
Marko Mikulicic 0:c0ecb8bf28eb 7555 i += c_itoa(buf + i, buf_size - i, num, 16, flags, 0);
Marko Mikulicic 0:c0ecb8bf28eb 7556 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7557 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 7558 /*
Marko Mikulicic 0:c0ecb8bf28eb 7559 * TODO(lsm): abort is not nice in a library, remove it
Marko Mikulicic 0:c0ecb8bf28eb 7560 * Also, ESP8266 SDK doesn't have it
Marko Mikulicic 0:c0ecb8bf28eb 7561 */
Marko Mikulicic 0:c0ecb8bf28eb 7562 abort();
Marko Mikulicic 0:c0ecb8bf28eb 7563 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7564 }
Marko Mikulicic 0:c0ecb8bf28eb 7565 }
Marko Mikulicic 0:c0ecb8bf28eb 7566 }
Marko Mikulicic 0:c0ecb8bf28eb 7567
Marko Mikulicic 0:c0ecb8bf28eb 7568 /* Zero-terminate the result */
Marko Mikulicic 0:c0ecb8bf28eb 7569 if (buf_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7570 buf[i < (int) buf_size ? i : (int) buf_size - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 7571 }
Marko Mikulicic 0:c0ecb8bf28eb 7572
Marko Mikulicic 0:c0ecb8bf28eb 7573 return i;
Marko Mikulicic 0:c0ecb8bf28eb 7574 }
Marko Mikulicic 0:c0ecb8bf28eb 7575 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7576
Marko Mikulicic 0:c0ecb8bf28eb 7577 int c_snprintf(char *buf, size_t buf_size, const char *fmt, ...) {
Marko Mikulicic 0:c0ecb8bf28eb 7578 int result;
Marko Mikulicic 0:c0ecb8bf28eb 7579 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 7580 va_start(ap, fmt);
Marko Mikulicic 0:c0ecb8bf28eb 7581 result = c_vsnprintf(buf, buf_size, fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 7582 va_end(ap);
Marko Mikulicic 0:c0ecb8bf28eb 7583 return result;
Marko Mikulicic 0:c0ecb8bf28eb 7584 }
Marko Mikulicic 0:c0ecb8bf28eb 7585
Marko Mikulicic 0:c0ecb8bf28eb 7586 #ifdef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 7587 int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) {
Marko Mikulicic 0:c0ecb8bf28eb 7588 int ret;
Marko Mikulicic 0:c0ecb8bf28eb 7589 char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p;
Marko Mikulicic 0:c0ecb8bf28eb 7590
Marko Mikulicic 0:c0ecb8bf28eb 7591 strncpy(buf, path, sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 7592 buf[sizeof(buf) - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 7593
Marko Mikulicic 0:c0ecb8bf28eb 7594 /* Trim trailing slashes. Leave backslash for paths like "X:\" */
Marko Mikulicic 0:c0ecb8bf28eb 7595 p = buf + strlen(buf) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 7596 while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 7597
Marko Mikulicic 0:c0ecb8bf28eb 7598 memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
Marko Mikulicic 0:c0ecb8bf28eb 7599 ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
Marko Mikulicic 0:c0ecb8bf28eb 7600
Marko Mikulicic 0:c0ecb8bf28eb 7601 /*
Marko Mikulicic 0:c0ecb8bf28eb 7602 * Convert back to Unicode. If doubly-converted string does not match the
Marko Mikulicic 0:c0ecb8bf28eb 7603 * original, something is fishy, reject.
Marko Mikulicic 0:c0ecb8bf28eb 7604 */
Marko Mikulicic 0:c0ecb8bf28eb 7605 WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
Marko Mikulicic 0:c0ecb8bf28eb 7606 NULL, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 7607 if (strcmp(buf, buf2) != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7608 wbuf[0] = L'\0';
Marko Mikulicic 0:c0ecb8bf28eb 7609 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7610 }
Marko Mikulicic 0:c0ecb8bf28eb 7611
Marko Mikulicic 0:c0ecb8bf28eb 7612 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 7613 }
Marko Mikulicic 0:c0ecb8bf28eb 7614 #endif /* _WIN32 */
Marko Mikulicic 0:c0ecb8bf28eb 7615
Marko Mikulicic 0:c0ecb8bf28eb 7616 /* The simplest O(mn) algorithm. Better implementation are GPLed */
Marko Mikulicic 0:c0ecb8bf28eb 7617 const char *c_strnstr(const char *s, const char *find, size_t slen) {
Marko Mikulicic 0:c0ecb8bf28eb 7618 size_t find_length = strlen(find);
Marko Mikulicic 0:c0ecb8bf28eb 7619 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 7620
Marko Mikulicic 0:c0ecb8bf28eb 7621 for (i = 0; i < slen; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 7622 if (i + find_length > slen) {
Marko Mikulicic 0:c0ecb8bf28eb 7623 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7624 }
Marko Mikulicic 0:c0ecb8bf28eb 7625
Marko Mikulicic 0:c0ecb8bf28eb 7626 if (strncmp(&s[i], find, find_length) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7627 return &s[i];
Marko Mikulicic 0:c0ecb8bf28eb 7628 }
Marko Mikulicic 0:c0ecb8bf28eb 7629 }
Marko Mikulicic 0:c0ecb8bf28eb 7630
Marko Mikulicic 0:c0ecb8bf28eb 7631 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7632 }
Marko Mikulicic 0:c0ecb8bf28eb 7633
Marko Mikulicic 0:c0ecb8bf28eb 7634 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 7635 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7636 #line 1 "common/utf.c"
Marko Mikulicic 0:c0ecb8bf28eb 7637 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7638 /*
Marko Mikulicic 0:c0ecb8bf28eb 7639 * The authors of this software are Rob Pike and Ken Thompson.
Marko Mikulicic 0:c0ecb8bf28eb 7640 * Copyright (c) 2002 by Lucent Technologies.
Marko Mikulicic 0:c0ecb8bf28eb 7641 * Permission to use, copy, modify, and distribute this software for any
Marko Mikulicic 0:c0ecb8bf28eb 7642 * purpose without fee is hereby granted, provided that this entire notice
Marko Mikulicic 0:c0ecb8bf28eb 7643 * is included in all copies of any software which is or includes a copy
Marko Mikulicic 0:c0ecb8bf28eb 7644 * or modification of this software and in all copies of the supporting
Marko Mikulicic 0:c0ecb8bf28eb 7645 * documentation for such software.
Marko Mikulicic 0:c0ecb8bf28eb 7646 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
Marko Mikulicic 0:c0ecb8bf28eb 7647 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
Marko Mikulicic 0:c0ecb8bf28eb 7648 * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
Marko Mikulicic 0:c0ecb8bf28eb 7649 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 7650 */
Marko Mikulicic 0:c0ecb8bf28eb 7651
Marko Mikulicic 0:c0ecb8bf28eb 7652 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 7653
Marko Mikulicic 0:c0ecb8bf28eb 7654 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 7655
Marko Mikulicic 0:c0ecb8bf28eb 7656 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 7657 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 7658 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7659 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7660
Marko Mikulicic 0:c0ecb8bf28eb 7661 #if CS_ENABLE_UTF8
Marko Mikulicic 0:c0ecb8bf28eb 7662 enum {
Marko Mikulicic 0:c0ecb8bf28eb 7663 Bit1 = 7,
Marko Mikulicic 0:c0ecb8bf28eb 7664 Bitx = 6,
Marko Mikulicic 0:c0ecb8bf28eb 7665 Bit2 = 5,
Marko Mikulicic 0:c0ecb8bf28eb 7666 Bit3 = 4,
Marko Mikulicic 0:c0ecb8bf28eb 7667 Bit4 = 3,
Marko Mikulicic 0:c0ecb8bf28eb 7668 Bit5 = 2,
Marko Mikulicic 0:c0ecb8bf28eb 7669
Marko Mikulicic 0:c0ecb8bf28eb 7670 T1 = ((1 << (Bit1 + 1)) - 1) ^ 0xFF, /* 0000 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7671 Tx = ((1 << (Bitx + 1)) - 1) ^ 0xFF, /* 1000 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7672 T2 = ((1 << (Bit2 + 1)) - 1) ^ 0xFF, /* 1100 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7673 T3 = ((1 << (Bit3 + 1)) - 1) ^ 0xFF, /* 1110 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7674 T4 = ((1 << (Bit4 + 1)) - 1) ^ 0xFF, /* 1111 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7675 T5 = ((1 << (Bit5 + 1)) - 1) ^ 0xFF, /* 1111 1000 */
Marko Mikulicic 0:c0ecb8bf28eb 7676
Marko Mikulicic 0:c0ecb8bf28eb 7677 Rune1 = (1 << (Bit1 + 0 * Bitx)) - 1, /* 0000 0000 0000 0000 0111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7678 Rune2 = (1 << (Bit2 + 1 * Bitx)) - 1, /* 0000 0000 0000 0111 1111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7679 Rune3 = (1 << (Bit3 + 2 * Bitx)) - 1, /* 0000 0000 1111 1111 1111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7680 Rune4 = (1 << (Bit4 + 3 * Bitx)) - 1, /* 0011 1111 1111 1111 1111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7681
Marko Mikulicic 0:c0ecb8bf28eb 7682 Maskx = (1 << Bitx) - 1, /* 0011 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7683 Testx = Maskx ^ 0xFF, /* 1100 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7684
Marko Mikulicic 0:c0ecb8bf28eb 7685 Bad = Runeerror
Marko Mikulicic 0:c0ecb8bf28eb 7686 };
Marko Mikulicic 0:c0ecb8bf28eb 7687
Marko Mikulicic 0:c0ecb8bf28eb 7688 int chartorune(Rune *rune, const char *str) {
Marko Mikulicic 0:c0ecb8bf28eb 7689 int c, c1, c2 /* , c3 */;
Marko Mikulicic 0:c0ecb8bf28eb 7690 unsigned short l;
Marko Mikulicic 0:c0ecb8bf28eb 7691
Marko Mikulicic 0:c0ecb8bf28eb 7692 /*
Marko Mikulicic 0:c0ecb8bf28eb 7693 * one character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7694 * 00000-0007F => T1
Marko Mikulicic 0:c0ecb8bf28eb 7695 */
Marko Mikulicic 0:c0ecb8bf28eb 7696 c = *(uchar *) str;
Marko Mikulicic 0:c0ecb8bf28eb 7697 if (c < Tx) {
Marko Mikulicic 0:c0ecb8bf28eb 7698 *rune = c;
Marko Mikulicic 0:c0ecb8bf28eb 7699 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7700 }
Marko Mikulicic 0:c0ecb8bf28eb 7701
Marko Mikulicic 0:c0ecb8bf28eb 7702 /*
Marko Mikulicic 0:c0ecb8bf28eb 7703 * two character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7704 * 0080-07FF => T2 Tx
Marko Mikulicic 0:c0ecb8bf28eb 7705 */
Marko Mikulicic 0:c0ecb8bf28eb 7706 c1 = *(uchar *) (str + 1) ^ Tx;
Marko Mikulicic 0:c0ecb8bf28eb 7707 if (c1 & Testx) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7708 if (c < T3) {
Marko Mikulicic 0:c0ecb8bf28eb 7709 if (c < T2) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7710 l = ((c << Bitx) | c1) & Rune2;
Marko Mikulicic 0:c0ecb8bf28eb 7711 if (l <= Rune1) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7712 *rune = l;
Marko Mikulicic 0:c0ecb8bf28eb 7713 return 2;
Marko Mikulicic 0:c0ecb8bf28eb 7714 }
Marko Mikulicic 0:c0ecb8bf28eb 7715
Marko Mikulicic 0:c0ecb8bf28eb 7716 /*
Marko Mikulicic 0:c0ecb8bf28eb 7717 * three character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7718 * 0800-FFFF => T3 Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7719 */
Marko Mikulicic 0:c0ecb8bf28eb 7720 c2 = *(uchar *) (str + 2) ^ Tx;
Marko Mikulicic 0:c0ecb8bf28eb 7721 if (c2 & Testx) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7722 if (c < T4) {
Marko Mikulicic 0:c0ecb8bf28eb 7723 l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
Marko Mikulicic 0:c0ecb8bf28eb 7724 if (l <= Rune2) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7725 *rune = l;
Marko Mikulicic 0:c0ecb8bf28eb 7726 return 3;
Marko Mikulicic 0:c0ecb8bf28eb 7727 }
Marko Mikulicic 0:c0ecb8bf28eb 7728
Marko Mikulicic 0:c0ecb8bf28eb 7729 /*
Marko Mikulicic 0:c0ecb8bf28eb 7730 * four character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7731 * 10000-10FFFF => T4 Tx Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7732 */
Marko Mikulicic 0:c0ecb8bf28eb 7733 /* if(UTFmax >= 4) {
Marko Mikulicic 0:c0ecb8bf28eb 7734 c3 = *(uchar*)(str+3) ^ Tx;
Marko Mikulicic 0:c0ecb8bf28eb 7735 if(c3 & Testx)
Marko Mikulicic 0:c0ecb8bf28eb 7736 goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7737 if(c < T5) {
Marko Mikulicic 0:c0ecb8bf28eb 7738 l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) &
Marko Mikulicic 0:c0ecb8bf28eb 7739 Rune4;
Marko Mikulicic 0:c0ecb8bf28eb 7740 if(l <= Rune3)
Marko Mikulicic 0:c0ecb8bf28eb 7741 goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7742 if(l > Runemax)
Marko Mikulicic 0:c0ecb8bf28eb 7743 goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7744 *rune = l;
Marko Mikulicic 0:c0ecb8bf28eb 7745 return 4;
Marko Mikulicic 0:c0ecb8bf28eb 7746 }
Marko Mikulicic 0:c0ecb8bf28eb 7747 } */
Marko Mikulicic 0:c0ecb8bf28eb 7748
Marko Mikulicic 0:c0ecb8bf28eb 7749 /*
Marko Mikulicic 0:c0ecb8bf28eb 7750 * bad decoding
Marko Mikulicic 0:c0ecb8bf28eb 7751 */
Marko Mikulicic 0:c0ecb8bf28eb 7752 bad:
Marko Mikulicic 0:c0ecb8bf28eb 7753 *rune = Bad;
Marko Mikulicic 0:c0ecb8bf28eb 7754 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7755 }
Marko Mikulicic 0:c0ecb8bf28eb 7756
Marko Mikulicic 0:c0ecb8bf28eb 7757 int runetochar(char *str, Rune *rune) {
Marko Mikulicic 0:c0ecb8bf28eb 7758 unsigned short c;
Marko Mikulicic 0:c0ecb8bf28eb 7759
Marko Mikulicic 0:c0ecb8bf28eb 7760 /*
Marko Mikulicic 0:c0ecb8bf28eb 7761 * one character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7762 * 00000-0007F => 00-7F
Marko Mikulicic 0:c0ecb8bf28eb 7763 */
Marko Mikulicic 0:c0ecb8bf28eb 7764 c = *rune;
Marko Mikulicic 0:c0ecb8bf28eb 7765 if (c <= Rune1) {
Marko Mikulicic 0:c0ecb8bf28eb 7766 str[0] = c;
Marko Mikulicic 0:c0ecb8bf28eb 7767 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7768 }
Marko Mikulicic 0:c0ecb8bf28eb 7769
Marko Mikulicic 0:c0ecb8bf28eb 7770 /*
Marko Mikulicic 0:c0ecb8bf28eb 7771 * two character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7772 * 00080-007FF => T2 Tx
Marko Mikulicic 0:c0ecb8bf28eb 7773 */
Marko Mikulicic 0:c0ecb8bf28eb 7774 if (c <= Rune2) {
Marko Mikulicic 0:c0ecb8bf28eb 7775 str[0] = T2 | (c >> 1 * Bitx);
Marko Mikulicic 0:c0ecb8bf28eb 7776 str[1] = Tx | (c & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7777 return 2;
Marko Mikulicic 0:c0ecb8bf28eb 7778 }
Marko Mikulicic 0:c0ecb8bf28eb 7779
Marko Mikulicic 0:c0ecb8bf28eb 7780 /*
Marko Mikulicic 0:c0ecb8bf28eb 7781 * three character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7782 * 00800-0FFFF => T3 Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7783 */
Marko Mikulicic 0:c0ecb8bf28eb 7784 /* if(c > Runemax)
Marko Mikulicic 0:c0ecb8bf28eb 7785 c = Runeerror; */
Marko Mikulicic 0:c0ecb8bf28eb 7786 /* if(c <= Rune3) { */
Marko Mikulicic 0:c0ecb8bf28eb 7787 str[0] = T3 | (c >> 2 * Bitx);
Marko Mikulicic 0:c0ecb8bf28eb 7788 str[1] = Tx | ((c >> 1 * Bitx) & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7789 str[2] = Tx | (c & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7790 return 3;
Marko Mikulicic 0:c0ecb8bf28eb 7791 /* } */
Marko Mikulicic 0:c0ecb8bf28eb 7792
Marko Mikulicic 0:c0ecb8bf28eb 7793 /*
Marko Mikulicic 0:c0ecb8bf28eb 7794 * four character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7795 * 010000-1FFFFF => T4 Tx Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7796 */
Marko Mikulicic 0:c0ecb8bf28eb 7797 /* str[0] = T4 | (c >> 3*Bitx);
Marko Mikulicic 0:c0ecb8bf28eb 7798 str[1] = Tx | ((c >> 2*Bitx) & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7799 str[2] = Tx | ((c >> 1*Bitx) & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7800 str[3] = Tx | (c & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7801 return 4; */
Marko Mikulicic 0:c0ecb8bf28eb 7802 }
Marko Mikulicic 0:c0ecb8bf28eb 7803
Marko Mikulicic 0:c0ecb8bf28eb 7804 int fullrune(const char *str, int n) {
Marko Mikulicic 0:c0ecb8bf28eb 7805 int c;
Marko Mikulicic 0:c0ecb8bf28eb 7806
Marko Mikulicic 0:c0ecb8bf28eb 7807 if (n <= 0) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 7808 c = *(uchar *) str;
Marko Mikulicic 0:c0ecb8bf28eb 7809 if (c < Tx) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7810 if (c < T3) return n >= 2;
Marko Mikulicic 0:c0ecb8bf28eb 7811 if (UTFmax == 3 || c < T4) return n >= 3;
Marko Mikulicic 0:c0ecb8bf28eb 7812 return n >= 4;
Marko Mikulicic 0:c0ecb8bf28eb 7813 }
Marko Mikulicic 0:c0ecb8bf28eb 7814
Marko Mikulicic 0:c0ecb8bf28eb 7815 int utfnlen(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 7816 int c;
Marko Mikulicic 0:c0ecb8bf28eb 7817 long n;
Marko Mikulicic 0:c0ecb8bf28eb 7818 Rune rune;
Marko Mikulicic 0:c0ecb8bf28eb 7819 const char *es;
Marko Mikulicic 0:c0ecb8bf28eb 7820
Marko Mikulicic 0:c0ecb8bf28eb 7821 es = s + m;
Marko Mikulicic 0:c0ecb8bf28eb 7822 for (n = 0; s < es; n++) {
Marko Mikulicic 0:c0ecb8bf28eb 7823 c = *(uchar *) s;
Marko Mikulicic 0:c0ecb8bf28eb 7824 if (c < Runeself) {
Marko Mikulicic 0:c0ecb8bf28eb 7825 s++;
Marko Mikulicic 0:c0ecb8bf28eb 7826 continue;
Marko Mikulicic 0:c0ecb8bf28eb 7827 }
Marko Mikulicic 0:c0ecb8bf28eb 7828 if (!fullrune(s, es - s)) break;
Marko Mikulicic 0:c0ecb8bf28eb 7829 s += chartorune(&rune, s);
Marko Mikulicic 0:c0ecb8bf28eb 7830 }
Marko Mikulicic 0:c0ecb8bf28eb 7831 return n;
Marko Mikulicic 0:c0ecb8bf28eb 7832 }
Marko Mikulicic 0:c0ecb8bf28eb 7833
Marko Mikulicic 0:c0ecb8bf28eb 7834 const char *utfnshift(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 7835 int c;
Marko Mikulicic 0:c0ecb8bf28eb 7836 long n;
Marko Mikulicic 0:c0ecb8bf28eb 7837 Rune rune;
Marko Mikulicic 0:c0ecb8bf28eb 7838
Marko Mikulicic 0:c0ecb8bf28eb 7839 for (n = 0; n < m; n++) {
Marko Mikulicic 0:c0ecb8bf28eb 7840 c = *(uchar *) s;
Marko Mikulicic 0:c0ecb8bf28eb 7841 if (c < Runeself) {
Marko Mikulicic 0:c0ecb8bf28eb 7842 s++;
Marko Mikulicic 0:c0ecb8bf28eb 7843 continue;
Marko Mikulicic 0:c0ecb8bf28eb 7844 }
Marko Mikulicic 0:c0ecb8bf28eb 7845 s += chartorune(&rune, s);
Marko Mikulicic 0:c0ecb8bf28eb 7846 }
Marko Mikulicic 0:c0ecb8bf28eb 7847 return s;
Marko Mikulicic 0:c0ecb8bf28eb 7848 }
Marko Mikulicic 0:c0ecb8bf28eb 7849
Marko Mikulicic 0:c0ecb8bf28eb 7850 /*
Marko Mikulicic 0:c0ecb8bf28eb 7851 * The authors of this software are Rob Pike and Ken Thompson.
Marko Mikulicic 0:c0ecb8bf28eb 7852 * Copyright (c) 2002 by Lucent Technologies.
Marko Mikulicic 0:c0ecb8bf28eb 7853 * Permission to use, copy, modify, and distribute this software for any
Marko Mikulicic 0:c0ecb8bf28eb 7854 * purpose without fee is hereby granted, provided that this entire notice
Marko Mikulicic 0:c0ecb8bf28eb 7855 * is included in all copies of any software which is or includes a copy
Marko Mikulicic 0:c0ecb8bf28eb 7856 * or modification of this software and in all copies of the supporting
Marko Mikulicic 0:c0ecb8bf28eb 7857 * documentation for such software.
Marko Mikulicic 0:c0ecb8bf28eb 7858 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
Marko Mikulicic 0:c0ecb8bf28eb 7859 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
Marko Mikulicic 0:c0ecb8bf28eb 7860 * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
Marko Mikulicic 0:c0ecb8bf28eb 7861 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 7862 */
Marko Mikulicic 0:c0ecb8bf28eb 7863 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 7864 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 7865 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7866
Marko Mikulicic 0:c0ecb8bf28eb 7867 /*
Marko Mikulicic 0:c0ecb8bf28eb 7868 * alpha ranges -
Marko Mikulicic 0:c0ecb8bf28eb 7869 * only covers ranges not in lower||upper
Marko Mikulicic 0:c0ecb8bf28eb 7870 */
Marko Mikulicic 0:c0ecb8bf28eb 7871 static Rune __alpha2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 7872 0x00d8, 0x00f6, /* Ø - ö */
Marko Mikulicic 0:c0ecb8bf28eb 7873 0x00f8, 0x01f5, /* ø - ǵ */
Marko Mikulicic 0:c0ecb8bf28eb 7874 0x0250, 0x02a8, /* ɐ - ʨ */
Marko Mikulicic 0:c0ecb8bf28eb 7875 0x038e, 0x03a1, /* Ύ - Ρ */
Marko Mikulicic 0:c0ecb8bf28eb 7876 0x03a3, 0x03ce, /* Σ - ώ */
Marko Mikulicic 0:c0ecb8bf28eb 7877 0x03d0, 0x03d6, /* ϐ - ϖ */
Marko Mikulicic 0:c0ecb8bf28eb 7878 0x03e2, 0x03f3, /* Ϣ - ϳ */
Marko Mikulicic 0:c0ecb8bf28eb 7879 0x0490, 0x04c4, /* Ґ - ӄ */
Marko Mikulicic 0:c0ecb8bf28eb 7880 0x0561, 0x0587, /* ա - և */
Marko Mikulicic 0:c0ecb8bf28eb 7881 0x05d0, 0x05ea, /* א - ת */
Marko Mikulicic 0:c0ecb8bf28eb 7882 0x05f0, 0x05f2, /* װ - ײ */
Marko Mikulicic 0:c0ecb8bf28eb 7883 0x0621, 0x063a, /* ء - غ */
Marko Mikulicic 0:c0ecb8bf28eb 7884 0x0640, 0x064a, /* ـ - ي */
Marko Mikulicic 0:c0ecb8bf28eb 7885 0x0671, 0x06b7, /* ٱ - ڷ */
Marko Mikulicic 0:c0ecb8bf28eb 7886 0x06ba, 0x06be, /* ں - ھ */
Marko Mikulicic 0:c0ecb8bf28eb 7887 0x06c0, 0x06ce, /* ۀ - ێ */
Marko Mikulicic 0:c0ecb8bf28eb 7888 0x06d0, 0x06d3, /* ې - ۓ */
Marko Mikulicic 0:c0ecb8bf28eb 7889 0x0905, 0x0939, /* अ - ह */
Marko Mikulicic 0:c0ecb8bf28eb 7890 0x0958, 0x0961, /* क़ - ॡ */
Marko Mikulicic 0:c0ecb8bf28eb 7891 0x0985, 0x098c, /* অ - ঌ */
Marko Mikulicic 0:c0ecb8bf28eb 7892 0x098f, 0x0990, /* এ - ঐ */
Marko Mikulicic 0:c0ecb8bf28eb 7893 0x0993, 0x09a8, /* ও - ন */
Marko Mikulicic 0:c0ecb8bf28eb 7894 0x09aa, 0x09b0, /* প - র */
Marko Mikulicic 0:c0ecb8bf28eb 7895 0x09b6, 0x09b9, /* শ - হ */
Marko Mikulicic 0:c0ecb8bf28eb 7896 0x09dc, 0x09dd, /* ড় - ঢ় */
Marko Mikulicic 0:c0ecb8bf28eb 7897 0x09df, 0x09e1, /* য় - ৡ */
Marko Mikulicic 0:c0ecb8bf28eb 7898 0x09f0, 0x09f1, /* ৰ - ৱ */
Marko Mikulicic 0:c0ecb8bf28eb 7899 0x0a05, 0x0a0a, /* ਅ - ਊ */
Marko Mikulicic 0:c0ecb8bf28eb 7900 0x0a0f, 0x0a10, /* ਏ - ਐ */
Marko Mikulicic 0:c0ecb8bf28eb 7901 0x0a13, 0x0a28, /* ਓ - ਨ */
Marko Mikulicic 0:c0ecb8bf28eb 7902 0x0a2a, 0x0a30, /* ਪ - ਰ */
Marko Mikulicic 0:c0ecb8bf28eb 7903 0x0a32, 0x0a33, /* ਲ - ਲ਼ */
Marko Mikulicic 0:c0ecb8bf28eb 7904 0x0a35, 0x0a36, /* ਵ - ਸ਼ */
Marko Mikulicic 0:c0ecb8bf28eb 7905 0x0a38, 0x0a39, /* ਸ - ਹ */
Marko Mikulicic 0:c0ecb8bf28eb 7906 0x0a59, 0x0a5c, /* ਖ਼ - ੜ */
Marko Mikulicic 0:c0ecb8bf28eb 7907 0x0a85, 0x0a8b, /* અ - ઋ */
Marko Mikulicic 0:c0ecb8bf28eb 7908 0x0a8f, 0x0a91, /* એ - ઑ */
Marko Mikulicic 0:c0ecb8bf28eb 7909 0x0a93, 0x0aa8, /* ઓ - ન */
Marko Mikulicic 0:c0ecb8bf28eb 7910 0x0aaa, 0x0ab0, /* પ - ર */
Marko Mikulicic 0:c0ecb8bf28eb 7911 0x0ab2, 0x0ab3, /* લ - ળ */
Marko Mikulicic 0:c0ecb8bf28eb 7912 0x0ab5, 0x0ab9, /* વ - હ */
Marko Mikulicic 0:c0ecb8bf28eb 7913 0x0b05, 0x0b0c, /* ଅ - ଌ */
Marko Mikulicic 0:c0ecb8bf28eb 7914 0x0b0f, 0x0b10, /* ଏ - ଐ */
Marko Mikulicic 0:c0ecb8bf28eb 7915 0x0b13, 0x0b28, /* ଓ - ନ */
Marko Mikulicic 0:c0ecb8bf28eb 7916 0x0b2a, 0x0b30, /* ପ - ର */
Marko Mikulicic 0:c0ecb8bf28eb 7917 0x0b32, 0x0b33, /* ଲ - ଳ */
Marko Mikulicic 0:c0ecb8bf28eb 7918 0x0b36, 0x0b39, /* ଶ - ହ */
Marko Mikulicic 0:c0ecb8bf28eb 7919 0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */
Marko Mikulicic 0:c0ecb8bf28eb 7920 0x0b5f, 0x0b61, /* ୟ - ୡ */
Marko Mikulicic 0:c0ecb8bf28eb 7921 0x0b85, 0x0b8a, /* அ - ஊ */
Marko Mikulicic 0:c0ecb8bf28eb 7922 0x0b8e, 0x0b90, /* எ - ஐ */
Marko Mikulicic 0:c0ecb8bf28eb 7923 0x0b92, 0x0b95, /* ஒ - க */
Marko Mikulicic 0:c0ecb8bf28eb 7924 0x0b99, 0x0b9a, /* ங - ச */
Marko Mikulicic 0:c0ecb8bf28eb 7925 0x0b9e, 0x0b9f, /* ஞ - ட */
Marko Mikulicic 0:c0ecb8bf28eb 7926 0x0ba3, 0x0ba4, /* ண - த */
Marko Mikulicic 0:c0ecb8bf28eb 7927 0x0ba8, 0x0baa, /* ந - ப */
Marko Mikulicic 0:c0ecb8bf28eb 7928 0x0bae, 0x0bb5, /* ம - வ */
Marko Mikulicic 0:c0ecb8bf28eb 7929 0x0bb7, 0x0bb9, /* ஷ - ஹ */
Marko Mikulicic 0:c0ecb8bf28eb 7930 0x0c05, 0x0c0c, /* అ - ఌ */
Marko Mikulicic 0:c0ecb8bf28eb 7931 0x0c0e, 0x0c10, /* ఎ - ఐ */
Marko Mikulicic 0:c0ecb8bf28eb 7932 0x0c12, 0x0c28, /* ఒ - న */
Marko Mikulicic 0:c0ecb8bf28eb 7933 0x0c2a, 0x0c33, /* ప - ళ */
Marko Mikulicic 0:c0ecb8bf28eb 7934 0x0c35, 0x0c39, /* వ - హ */
Marko Mikulicic 0:c0ecb8bf28eb 7935 0x0c60, 0x0c61, /* ౠ - ౡ */
Marko Mikulicic 0:c0ecb8bf28eb 7936 0x0c85, 0x0c8c, /* ಅ - ಌ */
Marko Mikulicic 0:c0ecb8bf28eb 7937 0x0c8e, 0x0c90, /* ಎ - ಐ */
Marko Mikulicic 0:c0ecb8bf28eb 7938 0x0c92, 0x0ca8, /* ಒ - ನ */
Marko Mikulicic 0:c0ecb8bf28eb 7939 0x0caa, 0x0cb3, /* ಪ - ಳ */
Marko Mikulicic 0:c0ecb8bf28eb 7940 0x0cb5, 0x0cb9, /* ವ - ಹ */
Marko Mikulicic 0:c0ecb8bf28eb 7941 0x0ce0, 0x0ce1, /* ೠ - ೡ */
Marko Mikulicic 0:c0ecb8bf28eb 7942 0x0d05, 0x0d0c, /* അ - ഌ */
Marko Mikulicic 0:c0ecb8bf28eb 7943 0x0d0e, 0x0d10, /* എ - ഐ */
Marko Mikulicic 0:c0ecb8bf28eb 7944 0x0d12, 0x0d28, /* ഒ - ന */
Marko Mikulicic 0:c0ecb8bf28eb 7945 0x0d2a, 0x0d39, /* പ - ഹ */
Marko Mikulicic 0:c0ecb8bf28eb 7946 0x0d60, 0x0d61, /* ൠ - ൡ */
Marko Mikulicic 0:c0ecb8bf28eb 7947 0x0e01, 0x0e30, /* ก - ะ */
Marko Mikulicic 0:c0ecb8bf28eb 7948 0x0e32, 0x0e33, /* า - ำ */
Marko Mikulicic 0:c0ecb8bf28eb 7949 0x0e40, 0x0e46, /* เ - ๆ */
Marko Mikulicic 0:c0ecb8bf28eb 7950 0x0e5a, 0x0e5b, /* ๚ - ๛ */
Marko Mikulicic 0:c0ecb8bf28eb 7951 0x0e81, 0x0e82, /* ກ - ຂ */
Marko Mikulicic 0:c0ecb8bf28eb 7952 0x0e87, 0x0e88, /* ງ - ຈ */
Marko Mikulicic 0:c0ecb8bf28eb 7953 0x0e94, 0x0e97, /* ດ - ທ */
Marko Mikulicic 0:c0ecb8bf28eb 7954 0x0e99, 0x0e9f, /* ນ - ຟ */
Marko Mikulicic 0:c0ecb8bf28eb 7955 0x0ea1, 0x0ea3, /* ມ - ຣ */
Marko Mikulicic 0:c0ecb8bf28eb 7956 0x0eaa, 0x0eab, /* ສ - ຫ */
Marko Mikulicic 0:c0ecb8bf28eb 7957 0x0ead, 0x0eae, /* ອ - ຮ */
Marko Mikulicic 0:c0ecb8bf28eb 7958 0x0eb2, 0x0eb3, /* າ - ຳ */
Marko Mikulicic 0:c0ecb8bf28eb 7959 0x0ec0, 0x0ec4, /* ເ - ໄ */
Marko Mikulicic 0:c0ecb8bf28eb 7960 0x0edc, 0x0edd, /* ໜ - ໝ */
Marko Mikulicic 0:c0ecb8bf28eb 7961 0x0f18, 0x0f19, /* ༘ - ༙ */
Marko Mikulicic 0:c0ecb8bf28eb 7962 0x0f40, 0x0f47, /* ཀ - ཇ */
Marko Mikulicic 0:c0ecb8bf28eb 7963 0x0f49, 0x0f69, /* ཉ - ཀྵ */
Marko Mikulicic 0:c0ecb8bf28eb 7964 0x10d0, 0x10f6, /* ა - ჶ */
Marko Mikulicic 0:c0ecb8bf28eb 7965 0x1100, 0x1159, /* ᄀ - ᅙ */
Marko Mikulicic 0:c0ecb8bf28eb 7966 0x115f, 0x11a2, /* ᅟ - ᆢ */
Marko Mikulicic 0:c0ecb8bf28eb 7967 0x11a8, 0x11f9, /* ᆨ - ᇹ */
Marko Mikulicic 0:c0ecb8bf28eb 7968 0x1e00, 0x1e9b, /* Ḁ - ẛ */
Marko Mikulicic 0:c0ecb8bf28eb 7969 0x1f50, 0x1f57, /* ὐ - ὗ */
Marko Mikulicic 0:c0ecb8bf28eb 7970 0x1f80, 0x1fb4, /* ᾀ - ᾴ */
Marko Mikulicic 0:c0ecb8bf28eb 7971 0x1fb6, 0x1fbc, /* ᾶ - ᾼ */
Marko Mikulicic 0:c0ecb8bf28eb 7972 0x1fc2, 0x1fc4, /* ῂ - ῄ */
Marko Mikulicic 0:c0ecb8bf28eb 7973 0x1fc6, 0x1fcc, /* ῆ - ῌ */
Marko Mikulicic 0:c0ecb8bf28eb 7974 0x1fd0, 0x1fd3, /* ῐ - ΐ */
Marko Mikulicic 0:c0ecb8bf28eb 7975 0x1fd6, 0x1fdb, /* ῖ - Ί */
Marko Mikulicic 0:c0ecb8bf28eb 7976 0x1fe0, 0x1fec, /* ῠ - Ῥ */
Marko Mikulicic 0:c0ecb8bf28eb 7977 0x1ff2, 0x1ff4, /* ῲ - ῴ */
Marko Mikulicic 0:c0ecb8bf28eb 7978 0x1ff6, 0x1ffc, /* ῶ - ῼ */
Marko Mikulicic 0:c0ecb8bf28eb 7979 0x210a, 0x2113, /* ℊ - ℓ */
Marko Mikulicic 0:c0ecb8bf28eb 7980 0x2115, 0x211d, /* ℕ - ℝ */
Marko Mikulicic 0:c0ecb8bf28eb 7981 0x2120, 0x2122, /* ℠ - ™ */
Marko Mikulicic 0:c0ecb8bf28eb 7982 0x212a, 0x2131, /* K - ℱ */
Marko Mikulicic 0:c0ecb8bf28eb 7983 0x2133, 0x2138, /* ℳ - ℸ */
Marko Mikulicic 0:c0ecb8bf28eb 7984 0x3041, 0x3094, /* ぁ - ゔ */
Marko Mikulicic 0:c0ecb8bf28eb 7985 0x30a1, 0x30fa, /* ァ - ヺ */
Marko Mikulicic 0:c0ecb8bf28eb 7986 0x3105, 0x312c, /* ㄅ - ㄬ */
Marko Mikulicic 0:c0ecb8bf28eb 7987 0x3131, 0x318e, /* ㄱ - ㆎ */
Marko Mikulicic 0:c0ecb8bf28eb 7988 0x3192, 0x319f, /* ㆒ - ㆟ */
Marko Mikulicic 0:c0ecb8bf28eb 7989 0x3260, 0x327b, /* ㉠ - ㉻ */
Marko Mikulicic 0:c0ecb8bf28eb 7990 0x328a, 0x32b0, /* ㊊ - ㊰ */
Marko Mikulicic 0:c0ecb8bf28eb 7991 0x32d0, 0x32fe, /* ㋐ - ㋾ */
Marko Mikulicic 0:c0ecb8bf28eb 7992 0x3300, 0x3357, /* ㌀ - ㍗ */
Marko Mikulicic 0:c0ecb8bf28eb 7993 0x3371, 0x3376, /* ㍱ - ㍶ */
Marko Mikulicic 0:c0ecb8bf28eb 7994 0x337b, 0x3394, /* ㍻ - ㎔ */
Marko Mikulicic 0:c0ecb8bf28eb 7995 0x3399, 0x339e, /* ㎙ - ㎞ */
Marko Mikulicic 0:c0ecb8bf28eb 7996 0x33a9, 0x33ad, /* ㎩ - ㎭ */
Marko Mikulicic 0:c0ecb8bf28eb 7997 0x33b0, 0x33c1, /* ㎰ - ㏁ */
Marko Mikulicic 0:c0ecb8bf28eb 7998 0x33c3, 0x33c5, /* ㏃ - ㏅ */
Marko Mikulicic 0:c0ecb8bf28eb 7999 0x33c7, 0x33d7, /* ㏇ - ㏗ */
Marko Mikulicic 0:c0ecb8bf28eb 8000 0x33d9, 0x33dd, /* ㏙ - ㏝ */
Marko Mikulicic 0:c0ecb8bf28eb 8001 0x4e00, 0x9fff, /* 一 - 鿿 */
Marko Mikulicic 0:c0ecb8bf28eb 8002 0xac00, 0xd7a3, /* 가 - 힣 */
Marko Mikulicic 0:c0ecb8bf28eb 8003 0xf900, 0xfb06, /* 豈 - st */
Marko Mikulicic 0:c0ecb8bf28eb 8004 0xfb13, 0xfb17, /* ﬓ - ﬗ */
Marko Mikulicic 0:c0ecb8bf28eb 8005 0xfb1f, 0xfb28, /* ײַ - ﬨ */
Marko Mikulicic 0:c0ecb8bf28eb 8006 0xfb2a, 0xfb36, /* שׁ - זּ */
Marko Mikulicic 0:c0ecb8bf28eb 8007 0xfb38, 0xfb3c, /* טּ - לּ */
Marko Mikulicic 0:c0ecb8bf28eb 8008 0xfb40, 0xfb41, /* נּ - סּ */
Marko Mikulicic 0:c0ecb8bf28eb 8009 0xfb43, 0xfb44, /* ףּ - פּ */
Marko Mikulicic 0:c0ecb8bf28eb 8010 0xfb46, 0xfbb1, /* צּ - ﮱ */
Marko Mikulicic 0:c0ecb8bf28eb 8011 0xfbd3, 0xfd3d, /* ﯓ - ﴽ */
Marko Mikulicic 0:c0ecb8bf28eb 8012 0xfd50, 0xfd8f, /* ﵐ - ﶏ */
Marko Mikulicic 0:c0ecb8bf28eb 8013 0xfd92, 0xfdc7, /* ﶒ - ﷇ */
Marko Mikulicic 0:c0ecb8bf28eb 8014 0xfdf0, 0xfdf9, /* ﷰ - ﷹ */
Marko Mikulicic 0:c0ecb8bf28eb 8015 0xfe70, 0xfe72, /* ﹰ - ﹲ */
Marko Mikulicic 0:c0ecb8bf28eb 8016 0xfe76, 0xfefc, /* ﹶ - ﻼ */
Marko Mikulicic 0:c0ecb8bf28eb 8017 0xff66, 0xff6f, /* ヲ - ッ */
Marko Mikulicic 0:c0ecb8bf28eb 8018 0xff71, 0xff9d, /* ア - ン */
Marko Mikulicic 0:c0ecb8bf28eb 8019 0xffa0, 0xffbe, /* ᅠ - ᄒ */
Marko Mikulicic 0:c0ecb8bf28eb 8020 0xffc2, 0xffc7, /* ᅡ - ᅦ */
Marko Mikulicic 0:c0ecb8bf28eb 8021 0xffca, 0xffcf, /* ᅧ - ᅬ */
Marko Mikulicic 0:c0ecb8bf28eb 8022 0xffd2, 0xffd7, /* ᅭ - ᅲ */
Marko Mikulicic 0:c0ecb8bf28eb 8023 0xffda, 0xffdc, /* ᅳ - ᅵ */
Marko Mikulicic 0:c0ecb8bf28eb 8024 };
Marko Mikulicic 0:c0ecb8bf28eb 8025
Marko Mikulicic 0:c0ecb8bf28eb 8026 /*
Marko Mikulicic 0:c0ecb8bf28eb 8027 * alpha singlets -
Marko Mikulicic 0:c0ecb8bf28eb 8028 * only covers ranges not in lower||upper
Marko Mikulicic 0:c0ecb8bf28eb 8029 */
Marko Mikulicic 0:c0ecb8bf28eb 8030 static Rune __alpha1[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8031 0x00aa, /* ª */
Marko Mikulicic 0:c0ecb8bf28eb 8032 0x00b5, /* µ */
Marko Mikulicic 0:c0ecb8bf28eb 8033 0x00ba, /* º */
Marko Mikulicic 0:c0ecb8bf28eb 8034 0x03da, /* Ϛ */
Marko Mikulicic 0:c0ecb8bf28eb 8035 0x03dc, /* Ϝ */
Marko Mikulicic 0:c0ecb8bf28eb 8036 0x03de, /* Ϟ */
Marko Mikulicic 0:c0ecb8bf28eb 8037 0x03e0, /* Ϡ */
Marko Mikulicic 0:c0ecb8bf28eb 8038 0x06d5, /* ە */
Marko Mikulicic 0:c0ecb8bf28eb 8039 0x09b2, /* ল */
Marko Mikulicic 0:c0ecb8bf28eb 8040 0x0a5e, /* ਫ਼ */
Marko Mikulicic 0:c0ecb8bf28eb 8041 0x0a8d, /* ઍ */
Marko Mikulicic 0:c0ecb8bf28eb 8042 0x0ae0, /* ૠ */
Marko Mikulicic 0:c0ecb8bf28eb 8043 0x0b9c, /* ஜ */
Marko Mikulicic 0:c0ecb8bf28eb 8044 0x0cde, /* ೞ */
Marko Mikulicic 0:c0ecb8bf28eb 8045 0x0e4f, /* ๏ */
Marko Mikulicic 0:c0ecb8bf28eb 8046 0x0e84, /* ຄ */
Marko Mikulicic 0:c0ecb8bf28eb 8047 0x0e8a, /* ຊ */
Marko Mikulicic 0:c0ecb8bf28eb 8048 0x0e8d, /* ຍ */
Marko Mikulicic 0:c0ecb8bf28eb 8049 0x0ea5, /* ລ */
Marko Mikulicic 0:c0ecb8bf28eb 8050 0x0ea7, /* ວ */
Marko Mikulicic 0:c0ecb8bf28eb 8051 0x0eb0, /* ະ */
Marko Mikulicic 0:c0ecb8bf28eb 8052 0x0ebd, /* ຽ */
Marko Mikulicic 0:c0ecb8bf28eb 8053 0x1fbe, /* ι */
Marko Mikulicic 0:c0ecb8bf28eb 8054 0x207f, /* ⁿ */
Marko Mikulicic 0:c0ecb8bf28eb 8055 0x20a8, /* ₨ */
Marko Mikulicic 0:c0ecb8bf28eb 8056 0x2102, /* ℂ */
Marko Mikulicic 0:c0ecb8bf28eb 8057 0x2107, /* ℇ */
Marko Mikulicic 0:c0ecb8bf28eb 8058 0x2124, /* ℤ */
Marko Mikulicic 0:c0ecb8bf28eb 8059 0x2126, /* Ω */
Marko Mikulicic 0:c0ecb8bf28eb 8060 0x2128, /* ℨ */
Marko Mikulicic 0:c0ecb8bf28eb 8061 0xfb3e, /* מּ */
Marko Mikulicic 0:c0ecb8bf28eb 8062 0xfe74, /* ﹴ */
Marko Mikulicic 0:c0ecb8bf28eb 8063 };
Marko Mikulicic 0:c0ecb8bf28eb 8064
Marko Mikulicic 0:c0ecb8bf28eb 8065 /*
Marko Mikulicic 0:c0ecb8bf28eb 8066 * space ranges
Marko Mikulicic 0:c0ecb8bf28eb 8067 */
Marko Mikulicic 0:c0ecb8bf28eb 8068 static Rune __space2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8069 0x0009, 0x000a, /* tab and newline */
Marko Mikulicic 0:c0ecb8bf28eb 8070 0x0020, 0x0020, /* space */
Marko Mikulicic 0:c0ecb8bf28eb 8071 0x00a0, 0x00a0, /*   */
Marko Mikulicic 0:c0ecb8bf28eb 8072 0x2000, 0x200b, /*   - ​ */
Marko Mikulicic 0:c0ecb8bf28eb 8073 0x2028, 0x2029, /* 
 - 
 */
Marko Mikulicic 0:c0ecb8bf28eb 8074 0x3000, 0x3000, /*   */
Marko Mikulicic 0:c0ecb8bf28eb 8075 0xfeff, 0xfeff, /*  */
Marko Mikulicic 0:c0ecb8bf28eb 8076 };
Marko Mikulicic 0:c0ecb8bf28eb 8077
Marko Mikulicic 0:c0ecb8bf28eb 8078 /*
Marko Mikulicic 0:c0ecb8bf28eb 8079 * lower case ranges
Marko Mikulicic 0:c0ecb8bf28eb 8080 * 3rd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8081 */
Marko Mikulicic 0:c0ecb8bf28eb 8082 static Rune __toupper2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8083 0x0061, 0x007a, 468, /* a-z A-Z */
Marko Mikulicic 0:c0ecb8bf28eb 8084 0x00e0, 0x00f6, 468, /* à-ö À-Ö */
Marko Mikulicic 0:c0ecb8bf28eb 8085 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */
Marko Mikulicic 0:c0ecb8bf28eb 8086 0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */
Marko Mikulicic 0:c0ecb8bf28eb 8087 0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */
Marko Mikulicic 0:c0ecb8bf28eb 8088 0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */
Marko Mikulicic 0:c0ecb8bf28eb 8089 0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */
Marko Mikulicic 0:c0ecb8bf28eb 8090 0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */
Marko Mikulicic 0:c0ecb8bf28eb 8091 0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */
Marko Mikulicic 0:c0ecb8bf28eb 8092 0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8093 0x0430, 0x044f, 468, /* а-я А-Я */
Marko Mikulicic 0:c0ecb8bf28eb 8094 0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */
Marko Mikulicic 0:c0ecb8bf28eb 8095 0x045e, 0x045f, 420, /* ў-џ Ў-Џ */
Marko Mikulicic 0:c0ecb8bf28eb 8096 0x0561, 0x0586, 452, /* ա-ֆ Ա-Ֆ */
Marko Mikulicic 0:c0ecb8bf28eb 8097 0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */
Marko Mikulicic 0:c0ecb8bf28eb 8098 0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */
Marko Mikulicic 0:c0ecb8bf28eb 8099 0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */
Marko Mikulicic 0:c0ecb8bf28eb 8100 0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */
Marko Mikulicic 0:c0ecb8bf28eb 8101 0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */
Marko Mikulicic 0:c0ecb8bf28eb 8102 0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */
Marko Mikulicic 0:c0ecb8bf28eb 8103 0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */
Marko Mikulicic 0:c0ecb8bf28eb 8104 0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */
Marko Mikulicic 0:c0ecb8bf28eb 8105 0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */
Marko Mikulicic 0:c0ecb8bf28eb 8106 0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */
Marko Mikulicic 0:c0ecb8bf28eb 8107 0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */
Marko Mikulicic 0:c0ecb8bf28eb 8108 0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8109 0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */
Marko Mikulicic 0:c0ecb8bf28eb 8110 0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */
Marko Mikulicic 0:c0ecb8bf28eb 8111 0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */
Marko Mikulicic 0:c0ecb8bf28eb 8112 0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */
Marko Mikulicic 0:c0ecb8bf28eb 8113 0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */
Marko Mikulicic 0:c0ecb8bf28eb 8114 0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */
Marko Mikulicic 0:c0ecb8bf28eb 8115 0x2170, 0x217f, 484, /* ⅰ-ⅿ Ⅰ-Ⅿ */
Marko Mikulicic 0:c0ecb8bf28eb 8116 0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */
Marko Mikulicic 0:c0ecb8bf28eb 8117 0xff41, 0xff5a, 468, /* a-z A-Z */
Marko Mikulicic 0:c0ecb8bf28eb 8118 };
Marko Mikulicic 0:c0ecb8bf28eb 8119
Marko Mikulicic 0:c0ecb8bf28eb 8120 /*
Marko Mikulicic 0:c0ecb8bf28eb 8121 * lower case singlets
Marko Mikulicic 0:c0ecb8bf28eb 8122 * 2nd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8123 */
Marko Mikulicic 0:c0ecb8bf28eb 8124 static Rune __toupper1[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8125 0x00ff, 621, /* ÿ Ÿ */
Marko Mikulicic 0:c0ecb8bf28eb 8126 0x0101, 499, /* ā Ā */
Marko Mikulicic 0:c0ecb8bf28eb 8127 0x0103, 499, /* ă Ă */
Marko Mikulicic 0:c0ecb8bf28eb 8128 0x0105, 499, /* ą Ą */
Marko Mikulicic 0:c0ecb8bf28eb 8129 0x0107, 499, /* ć Ć */
Marko Mikulicic 0:c0ecb8bf28eb 8130 0x0109, 499, /* ĉ Ĉ */
Marko Mikulicic 0:c0ecb8bf28eb 8131 0x010b, 499, /* ċ Ċ */
Marko Mikulicic 0:c0ecb8bf28eb 8132 0x010d, 499, /* č Č */
Marko Mikulicic 0:c0ecb8bf28eb 8133 0x010f, 499, /* ď Ď */
Marko Mikulicic 0:c0ecb8bf28eb 8134 0x0111, 499, /* đ Đ */
Marko Mikulicic 0:c0ecb8bf28eb 8135 0x0113, 499, /* ē Ē */
Marko Mikulicic 0:c0ecb8bf28eb 8136 0x0115, 499, /* ĕ Ĕ */
Marko Mikulicic 0:c0ecb8bf28eb 8137 0x0117, 499, /* ė Ė */
Marko Mikulicic 0:c0ecb8bf28eb 8138 0x0119, 499, /* ę Ę */
Marko Mikulicic 0:c0ecb8bf28eb 8139 0x011b, 499, /* ě Ě */
Marko Mikulicic 0:c0ecb8bf28eb 8140 0x011d, 499, /* ĝ Ĝ */
Marko Mikulicic 0:c0ecb8bf28eb 8141 0x011f, 499, /* ğ Ğ */
Marko Mikulicic 0:c0ecb8bf28eb 8142 0x0121, 499, /* ġ Ġ */
Marko Mikulicic 0:c0ecb8bf28eb 8143 0x0123, 499, /* ģ Ģ */
Marko Mikulicic 0:c0ecb8bf28eb 8144 0x0125, 499, /* ĥ Ĥ */
Marko Mikulicic 0:c0ecb8bf28eb 8145 0x0127, 499, /* ħ Ħ */
Marko Mikulicic 0:c0ecb8bf28eb 8146 0x0129, 499, /* ĩ Ĩ */
Marko Mikulicic 0:c0ecb8bf28eb 8147 0x012b, 499, /* ī Ī */
Marko Mikulicic 0:c0ecb8bf28eb 8148 0x012d, 499, /* ĭ Ĭ */
Marko Mikulicic 0:c0ecb8bf28eb 8149 0x012f, 499, /* į Į */
Marko Mikulicic 0:c0ecb8bf28eb 8150 0x0131, 268, /* ı I */
Marko Mikulicic 0:c0ecb8bf28eb 8151 0x0133, 499, /* ij IJ */
Marko Mikulicic 0:c0ecb8bf28eb 8152 0x0135, 499, /* ĵ Ĵ */
Marko Mikulicic 0:c0ecb8bf28eb 8153 0x0137, 499, /* ķ Ķ */
Marko Mikulicic 0:c0ecb8bf28eb 8154 0x013a, 499, /* ĺ Ĺ */
Marko Mikulicic 0:c0ecb8bf28eb 8155 0x013c, 499, /* ļ Ļ */
Marko Mikulicic 0:c0ecb8bf28eb 8156 0x013e, 499, /* ľ Ľ */
Marko Mikulicic 0:c0ecb8bf28eb 8157 0x0140, 499, /* ŀ Ŀ */
Marko Mikulicic 0:c0ecb8bf28eb 8158 0x0142, 499, /* ł Ł */
Marko Mikulicic 0:c0ecb8bf28eb 8159 0x0144, 499, /* ń Ń */
Marko Mikulicic 0:c0ecb8bf28eb 8160 0x0146, 499, /* ņ Ņ */
Marko Mikulicic 0:c0ecb8bf28eb 8161 0x0148, 499, /* ň Ň */
Marko Mikulicic 0:c0ecb8bf28eb 8162 0x014b, 499, /* ŋ Ŋ */
Marko Mikulicic 0:c0ecb8bf28eb 8163 0x014d, 499, /* ō Ō */
Marko Mikulicic 0:c0ecb8bf28eb 8164 0x014f, 499, /* ŏ Ŏ */
Marko Mikulicic 0:c0ecb8bf28eb 8165 0x0151, 499, /* ő Ő */
Marko Mikulicic 0:c0ecb8bf28eb 8166 0x0153, 499, /* œ Œ */
Marko Mikulicic 0:c0ecb8bf28eb 8167 0x0155, 499, /* ŕ Ŕ */
Marko Mikulicic 0:c0ecb8bf28eb 8168 0x0157, 499, /* ŗ Ŗ */
Marko Mikulicic 0:c0ecb8bf28eb 8169 0x0159, 499, /* ř Ř */
Marko Mikulicic 0:c0ecb8bf28eb 8170 0x015b, 499, /* ś Ś */
Marko Mikulicic 0:c0ecb8bf28eb 8171 0x015d, 499, /* ŝ Ŝ */
Marko Mikulicic 0:c0ecb8bf28eb 8172 0x015f, 499, /* ş Ş */
Marko Mikulicic 0:c0ecb8bf28eb 8173 0x0161, 499, /* š Š */
Marko Mikulicic 0:c0ecb8bf28eb 8174 0x0163, 499, /* ţ Ţ */
Marko Mikulicic 0:c0ecb8bf28eb 8175 0x0165, 499, /* ť Ť */
Marko Mikulicic 0:c0ecb8bf28eb 8176 0x0167, 499, /* ŧ Ŧ */
Marko Mikulicic 0:c0ecb8bf28eb 8177 0x0169, 499, /* ũ Ũ */
Marko Mikulicic 0:c0ecb8bf28eb 8178 0x016b, 499, /* ū Ū */
Marko Mikulicic 0:c0ecb8bf28eb 8179 0x016d, 499, /* ŭ Ŭ */
Marko Mikulicic 0:c0ecb8bf28eb 8180 0x016f, 499, /* ů Ů */
Marko Mikulicic 0:c0ecb8bf28eb 8181 0x0171, 499, /* ű Ű */
Marko Mikulicic 0:c0ecb8bf28eb 8182 0x0173, 499, /* ų Ų */
Marko Mikulicic 0:c0ecb8bf28eb 8183 0x0175, 499, /* ŵ Ŵ */
Marko Mikulicic 0:c0ecb8bf28eb 8184 0x0177, 499, /* ŷ Ŷ */
Marko Mikulicic 0:c0ecb8bf28eb 8185 0x017a, 499, /* ź Ź */
Marko Mikulicic 0:c0ecb8bf28eb 8186 0x017c, 499, /* ż Ż */
Marko Mikulicic 0:c0ecb8bf28eb 8187 0x017e, 499, /* ž Ž */
Marko Mikulicic 0:c0ecb8bf28eb 8188 0x017f, 200, /* ſ S */
Marko Mikulicic 0:c0ecb8bf28eb 8189 0x0183, 499, /* ƃ Ƃ */
Marko Mikulicic 0:c0ecb8bf28eb 8190 0x0185, 499, /* ƅ Ƅ */
Marko Mikulicic 0:c0ecb8bf28eb 8191 0x0188, 499, /* ƈ Ƈ */
Marko Mikulicic 0:c0ecb8bf28eb 8192 0x018c, 499, /* ƌ Ƌ */
Marko Mikulicic 0:c0ecb8bf28eb 8193 0x0192, 499, /* ƒ Ƒ */
Marko Mikulicic 0:c0ecb8bf28eb 8194 0x0199, 499, /* ƙ Ƙ */
Marko Mikulicic 0:c0ecb8bf28eb 8195 0x01a1, 499, /* ơ Ơ */
Marko Mikulicic 0:c0ecb8bf28eb 8196 0x01a3, 499, /* ƣ Ƣ */
Marko Mikulicic 0:c0ecb8bf28eb 8197 0x01a5, 499, /* ƥ Ƥ */
Marko Mikulicic 0:c0ecb8bf28eb 8198 0x01a8, 499, /* ƨ Ƨ */
Marko Mikulicic 0:c0ecb8bf28eb 8199 0x01ad, 499, /* ƭ Ƭ */
Marko Mikulicic 0:c0ecb8bf28eb 8200 0x01b0, 499, /* ư Ư */
Marko Mikulicic 0:c0ecb8bf28eb 8201 0x01b4, 499, /* ƴ Ƴ */
Marko Mikulicic 0:c0ecb8bf28eb 8202 0x01b6, 499, /* ƶ Ƶ */
Marko Mikulicic 0:c0ecb8bf28eb 8203 0x01b9, 499, /* ƹ Ƹ */
Marko Mikulicic 0:c0ecb8bf28eb 8204 0x01bd, 499, /* ƽ Ƽ */
Marko Mikulicic 0:c0ecb8bf28eb 8205 0x01c5, 499, /* Dž DŽ */
Marko Mikulicic 0:c0ecb8bf28eb 8206 0x01c6, 498, /* dž DŽ */
Marko Mikulicic 0:c0ecb8bf28eb 8207 0x01c8, 499, /* Lj LJ */
Marko Mikulicic 0:c0ecb8bf28eb 8208 0x01c9, 498, /* lj LJ */
Marko Mikulicic 0:c0ecb8bf28eb 8209 0x01cb, 499, /* Nj NJ */
Marko Mikulicic 0:c0ecb8bf28eb 8210 0x01cc, 498, /* nj NJ */
Marko Mikulicic 0:c0ecb8bf28eb 8211 0x01ce, 499, /* ǎ Ǎ */
Marko Mikulicic 0:c0ecb8bf28eb 8212 0x01d0, 499, /* ǐ Ǐ */
Marko Mikulicic 0:c0ecb8bf28eb 8213 0x01d2, 499, /* ǒ Ǒ */
Marko Mikulicic 0:c0ecb8bf28eb 8214 0x01d4, 499, /* ǔ Ǔ */
Marko Mikulicic 0:c0ecb8bf28eb 8215 0x01d6, 499, /* ǖ Ǖ */
Marko Mikulicic 0:c0ecb8bf28eb 8216 0x01d8, 499, /* ǘ Ǘ */
Marko Mikulicic 0:c0ecb8bf28eb 8217 0x01da, 499, /* ǚ Ǚ */
Marko Mikulicic 0:c0ecb8bf28eb 8218 0x01dc, 499, /* ǜ Ǜ */
Marko Mikulicic 0:c0ecb8bf28eb 8219 0x01df, 499, /* ǟ Ǟ */
Marko Mikulicic 0:c0ecb8bf28eb 8220 0x01e1, 499, /* ǡ Ǡ */
Marko Mikulicic 0:c0ecb8bf28eb 8221 0x01e3, 499, /* ǣ Ǣ */
Marko Mikulicic 0:c0ecb8bf28eb 8222 0x01e5, 499, /* ǥ Ǥ */
Marko Mikulicic 0:c0ecb8bf28eb 8223 0x01e7, 499, /* ǧ Ǧ */
Marko Mikulicic 0:c0ecb8bf28eb 8224 0x01e9, 499, /* ǩ Ǩ */
Marko Mikulicic 0:c0ecb8bf28eb 8225 0x01eb, 499, /* ǫ Ǫ */
Marko Mikulicic 0:c0ecb8bf28eb 8226 0x01ed, 499, /* ǭ Ǭ */
Marko Mikulicic 0:c0ecb8bf28eb 8227 0x01ef, 499, /* ǯ Ǯ */
Marko Mikulicic 0:c0ecb8bf28eb 8228 0x01f2, 499, /* Dz DZ */
Marko Mikulicic 0:c0ecb8bf28eb 8229 0x01f3, 498, /* dz DZ */
Marko Mikulicic 0:c0ecb8bf28eb 8230 0x01f5, 499, /* ǵ Ǵ */
Marko Mikulicic 0:c0ecb8bf28eb 8231 0x01fb, 499, /* ǻ Ǻ */
Marko Mikulicic 0:c0ecb8bf28eb 8232 0x01fd, 499, /* ǽ Ǽ */
Marko Mikulicic 0:c0ecb8bf28eb 8233 0x01ff, 499, /* ǿ Ǿ */
Marko Mikulicic 0:c0ecb8bf28eb 8234 0x0201, 499, /* ȁ Ȁ */
Marko Mikulicic 0:c0ecb8bf28eb 8235 0x0203, 499, /* ȃ Ȃ */
Marko Mikulicic 0:c0ecb8bf28eb 8236 0x0205, 499, /* ȅ Ȅ */
Marko Mikulicic 0:c0ecb8bf28eb 8237 0x0207, 499, /* ȇ Ȇ */
Marko Mikulicic 0:c0ecb8bf28eb 8238 0x0209, 499, /* ȉ Ȉ */
Marko Mikulicic 0:c0ecb8bf28eb 8239 0x020b, 499, /* ȋ Ȋ */
Marko Mikulicic 0:c0ecb8bf28eb 8240 0x020d, 499, /* ȍ Ȍ */
Marko Mikulicic 0:c0ecb8bf28eb 8241 0x020f, 499, /* ȏ Ȏ */
Marko Mikulicic 0:c0ecb8bf28eb 8242 0x0211, 499, /* ȑ Ȑ */
Marko Mikulicic 0:c0ecb8bf28eb 8243 0x0213, 499, /* ȓ Ȓ */
Marko Mikulicic 0:c0ecb8bf28eb 8244 0x0215, 499, /* ȕ Ȕ */
Marko Mikulicic 0:c0ecb8bf28eb 8245 0x0217, 499, /* ȗ Ȗ */
Marko Mikulicic 0:c0ecb8bf28eb 8246 0x0253, 290, /* ɓ Ɓ */
Marko Mikulicic 0:c0ecb8bf28eb 8247 0x0254, 294, /* ɔ Ɔ */
Marko Mikulicic 0:c0ecb8bf28eb 8248 0x025b, 297, /* ɛ Ɛ */
Marko Mikulicic 0:c0ecb8bf28eb 8249 0x0260, 295, /* ɠ Ɠ */
Marko Mikulicic 0:c0ecb8bf28eb 8250 0x0263, 293, /* ɣ Ɣ */
Marko Mikulicic 0:c0ecb8bf28eb 8251 0x0268, 291, /* ɨ Ɨ */
Marko Mikulicic 0:c0ecb8bf28eb 8252 0x0269, 289, /* ɩ Ɩ */
Marko Mikulicic 0:c0ecb8bf28eb 8253 0x026f, 289, /* ɯ Ɯ */
Marko Mikulicic 0:c0ecb8bf28eb 8254 0x0272, 287, /* ɲ Ɲ */
Marko Mikulicic 0:c0ecb8bf28eb 8255 0x0283, 282, /* ʃ Ʃ */
Marko Mikulicic 0:c0ecb8bf28eb 8256 0x0288, 282, /* ʈ Ʈ */
Marko Mikulicic 0:c0ecb8bf28eb 8257 0x0292, 281, /* ʒ Ʒ */
Marko Mikulicic 0:c0ecb8bf28eb 8258 0x03ac, 462, /* ά Ά */
Marko Mikulicic 0:c0ecb8bf28eb 8259 0x03cc, 436, /* ό Ό */
Marko Mikulicic 0:c0ecb8bf28eb 8260 0x03d0, 438, /* ϐ Β */
Marko Mikulicic 0:c0ecb8bf28eb 8261 0x03d1, 443, /* ϑ Θ */
Marko Mikulicic 0:c0ecb8bf28eb 8262 0x03d5, 453, /* ϕ Φ */
Marko Mikulicic 0:c0ecb8bf28eb 8263 0x03d6, 446, /* ϖ Π */
Marko Mikulicic 0:c0ecb8bf28eb 8264 0x03e3, 499, /* ϣ Ϣ */
Marko Mikulicic 0:c0ecb8bf28eb 8265 0x03e5, 499, /* ϥ Ϥ */
Marko Mikulicic 0:c0ecb8bf28eb 8266 0x03e7, 499, /* ϧ Ϧ */
Marko Mikulicic 0:c0ecb8bf28eb 8267 0x03e9, 499, /* ϩ Ϩ */
Marko Mikulicic 0:c0ecb8bf28eb 8268 0x03eb, 499, /* ϫ Ϫ */
Marko Mikulicic 0:c0ecb8bf28eb 8269 0x03ed, 499, /* ϭ Ϭ */
Marko Mikulicic 0:c0ecb8bf28eb 8270 0x03ef, 499, /* ϯ Ϯ */
Marko Mikulicic 0:c0ecb8bf28eb 8271 0x03f0, 414, /* ϰ Κ */
Marko Mikulicic 0:c0ecb8bf28eb 8272 0x03f1, 420, /* ϱ Ρ */
Marko Mikulicic 0:c0ecb8bf28eb 8273 0x0461, 499, /* ѡ Ѡ */
Marko Mikulicic 0:c0ecb8bf28eb 8274 0x0463, 499, /* ѣ Ѣ */
Marko Mikulicic 0:c0ecb8bf28eb 8275 0x0465, 499, /* ѥ Ѥ */
Marko Mikulicic 0:c0ecb8bf28eb 8276 0x0467, 499, /* ѧ Ѧ */
Marko Mikulicic 0:c0ecb8bf28eb 8277 0x0469, 499, /* ѩ Ѩ */
Marko Mikulicic 0:c0ecb8bf28eb 8278 0x046b, 499, /* ѫ Ѫ */
Marko Mikulicic 0:c0ecb8bf28eb 8279 0x046d, 499, /* ѭ Ѭ */
Marko Mikulicic 0:c0ecb8bf28eb 8280 0x046f, 499, /* ѯ Ѯ */
Marko Mikulicic 0:c0ecb8bf28eb 8281 0x0471, 499, /* ѱ Ѱ */
Marko Mikulicic 0:c0ecb8bf28eb 8282 0x0473, 499, /* ѳ Ѳ */
Marko Mikulicic 0:c0ecb8bf28eb 8283 0x0475, 499, /* ѵ Ѵ */
Marko Mikulicic 0:c0ecb8bf28eb 8284 0x0477, 499, /* ѷ Ѷ */
Marko Mikulicic 0:c0ecb8bf28eb 8285 0x0479, 499, /* ѹ Ѹ */
Marko Mikulicic 0:c0ecb8bf28eb 8286 0x047b, 499, /* ѻ Ѻ */
Marko Mikulicic 0:c0ecb8bf28eb 8287 0x047d, 499, /* ѽ Ѽ */
Marko Mikulicic 0:c0ecb8bf28eb 8288 0x047f, 499, /* ѿ Ѿ */
Marko Mikulicic 0:c0ecb8bf28eb 8289 0x0481, 499, /* ҁ Ҁ */
Marko Mikulicic 0:c0ecb8bf28eb 8290 0x0491, 499, /* ґ Ґ */
Marko Mikulicic 0:c0ecb8bf28eb 8291 0x0493, 499, /* ғ Ғ */
Marko Mikulicic 0:c0ecb8bf28eb 8292 0x0495, 499, /* ҕ Ҕ */
Marko Mikulicic 0:c0ecb8bf28eb 8293 0x0497, 499, /* җ Җ */
Marko Mikulicic 0:c0ecb8bf28eb 8294 0x0499, 499, /* ҙ Ҙ */
Marko Mikulicic 0:c0ecb8bf28eb 8295 0x049b, 499, /* қ Қ */
Marko Mikulicic 0:c0ecb8bf28eb 8296 0x049d, 499, /* ҝ Ҝ */
Marko Mikulicic 0:c0ecb8bf28eb 8297 0x049f, 499, /* ҟ Ҟ */
Marko Mikulicic 0:c0ecb8bf28eb 8298 0x04a1, 499, /* ҡ Ҡ */
Marko Mikulicic 0:c0ecb8bf28eb 8299 0x04a3, 499, /* ң Ң */
Marko Mikulicic 0:c0ecb8bf28eb 8300 0x04a5, 499, /* ҥ Ҥ */
Marko Mikulicic 0:c0ecb8bf28eb 8301 0x04a7, 499, /* ҧ Ҧ */
Marko Mikulicic 0:c0ecb8bf28eb 8302 0x04a9, 499, /* ҩ Ҩ */
Marko Mikulicic 0:c0ecb8bf28eb 8303 0x04ab, 499, /* ҫ Ҫ */
Marko Mikulicic 0:c0ecb8bf28eb 8304 0x04ad, 499, /* ҭ Ҭ */
Marko Mikulicic 0:c0ecb8bf28eb 8305 0x04af, 499, /* ү Ү */
Marko Mikulicic 0:c0ecb8bf28eb 8306 0x04b1, 499, /* ұ Ұ */
Marko Mikulicic 0:c0ecb8bf28eb 8307 0x04b3, 499, /* ҳ Ҳ */
Marko Mikulicic 0:c0ecb8bf28eb 8308 0x04b5, 499, /* ҵ Ҵ */
Marko Mikulicic 0:c0ecb8bf28eb 8309 0x04b7, 499, /* ҷ Ҷ */
Marko Mikulicic 0:c0ecb8bf28eb 8310 0x04b9, 499, /* ҹ Ҹ */
Marko Mikulicic 0:c0ecb8bf28eb 8311 0x04bb, 499, /* һ Һ */
Marko Mikulicic 0:c0ecb8bf28eb 8312 0x04bd, 499, /* ҽ Ҽ */
Marko Mikulicic 0:c0ecb8bf28eb 8313 0x04bf, 499, /* ҿ Ҿ */
Marko Mikulicic 0:c0ecb8bf28eb 8314 0x04c2, 499, /* ӂ Ӂ */
Marko Mikulicic 0:c0ecb8bf28eb 8315 0x04c4, 499, /* ӄ Ӄ */
Marko Mikulicic 0:c0ecb8bf28eb 8316 0x04c8, 499, /* ӈ Ӈ */
Marko Mikulicic 0:c0ecb8bf28eb 8317 0x04cc, 499, /* ӌ Ӌ */
Marko Mikulicic 0:c0ecb8bf28eb 8318 0x04d1, 499, /* ӑ Ӑ */
Marko Mikulicic 0:c0ecb8bf28eb 8319 0x04d3, 499, /* ӓ Ӓ */
Marko Mikulicic 0:c0ecb8bf28eb 8320 0x04d5, 499, /* ӕ Ӕ */
Marko Mikulicic 0:c0ecb8bf28eb 8321 0x04d7, 499, /* ӗ Ӗ */
Marko Mikulicic 0:c0ecb8bf28eb 8322 0x04d9, 499, /* ә Ә */
Marko Mikulicic 0:c0ecb8bf28eb 8323 0x04db, 499, /* ӛ Ӛ */
Marko Mikulicic 0:c0ecb8bf28eb 8324 0x04dd, 499, /* ӝ Ӝ */
Marko Mikulicic 0:c0ecb8bf28eb 8325 0x04df, 499, /* ӟ Ӟ */
Marko Mikulicic 0:c0ecb8bf28eb 8326 0x04e1, 499, /* ӡ Ӡ */
Marko Mikulicic 0:c0ecb8bf28eb 8327 0x04e3, 499, /* ӣ Ӣ */
Marko Mikulicic 0:c0ecb8bf28eb 8328 0x04e5, 499, /* ӥ Ӥ */
Marko Mikulicic 0:c0ecb8bf28eb 8329 0x04e7, 499, /* ӧ Ӧ */
Marko Mikulicic 0:c0ecb8bf28eb 8330 0x04e9, 499, /* ө Ө */
Marko Mikulicic 0:c0ecb8bf28eb 8331 0x04eb, 499, /* ӫ Ӫ */
Marko Mikulicic 0:c0ecb8bf28eb 8332 0x04ef, 499, /* ӯ Ӯ */
Marko Mikulicic 0:c0ecb8bf28eb 8333 0x04f1, 499, /* ӱ Ӱ */
Marko Mikulicic 0:c0ecb8bf28eb 8334 0x04f3, 499, /* ӳ Ӳ */
Marko Mikulicic 0:c0ecb8bf28eb 8335 0x04f5, 499, /* ӵ Ӵ */
Marko Mikulicic 0:c0ecb8bf28eb 8336 0x04f9, 499, /* ӹ Ӹ */
Marko Mikulicic 0:c0ecb8bf28eb 8337 0x1e01, 499, /* ḁ Ḁ */
Marko Mikulicic 0:c0ecb8bf28eb 8338 0x1e03, 499, /* ḃ Ḃ */
Marko Mikulicic 0:c0ecb8bf28eb 8339 0x1e05, 499, /* ḅ Ḅ */
Marko Mikulicic 0:c0ecb8bf28eb 8340 0x1e07, 499, /* ḇ Ḇ */
Marko Mikulicic 0:c0ecb8bf28eb 8341 0x1e09, 499, /* ḉ Ḉ */
Marko Mikulicic 0:c0ecb8bf28eb 8342 0x1e0b, 499, /* ḋ Ḋ */
Marko Mikulicic 0:c0ecb8bf28eb 8343 0x1e0d, 499, /* ḍ Ḍ */
Marko Mikulicic 0:c0ecb8bf28eb 8344 0x1e0f, 499, /* ḏ Ḏ */
Marko Mikulicic 0:c0ecb8bf28eb 8345 0x1e11, 499, /* ḑ Ḑ */
Marko Mikulicic 0:c0ecb8bf28eb 8346 0x1e13, 499, /* ḓ Ḓ */
Marko Mikulicic 0:c0ecb8bf28eb 8347 0x1e15, 499, /* ḕ Ḕ */
Marko Mikulicic 0:c0ecb8bf28eb 8348 0x1e17, 499, /* ḗ Ḗ */
Marko Mikulicic 0:c0ecb8bf28eb 8349 0x1e19, 499, /* ḙ Ḙ */
Marko Mikulicic 0:c0ecb8bf28eb 8350 0x1e1b, 499, /* ḛ Ḛ */
Marko Mikulicic 0:c0ecb8bf28eb 8351 0x1e1d, 499, /* ḝ Ḝ */
Marko Mikulicic 0:c0ecb8bf28eb 8352 0x1e1f, 499, /* ḟ Ḟ */
Marko Mikulicic 0:c0ecb8bf28eb 8353 0x1e21, 499, /* ḡ Ḡ */
Marko Mikulicic 0:c0ecb8bf28eb 8354 0x1e23, 499, /* ḣ Ḣ */
Marko Mikulicic 0:c0ecb8bf28eb 8355 0x1e25, 499, /* ḥ Ḥ */
Marko Mikulicic 0:c0ecb8bf28eb 8356 0x1e27, 499, /* ḧ Ḧ */
Marko Mikulicic 0:c0ecb8bf28eb 8357 0x1e29, 499, /* ḩ Ḩ */
Marko Mikulicic 0:c0ecb8bf28eb 8358 0x1e2b, 499, /* ḫ Ḫ */
Marko Mikulicic 0:c0ecb8bf28eb 8359 0x1e2d, 499, /* ḭ Ḭ */
Marko Mikulicic 0:c0ecb8bf28eb 8360 0x1e2f, 499, /* ḯ Ḯ */
Marko Mikulicic 0:c0ecb8bf28eb 8361 0x1e31, 499, /* ḱ Ḱ */
Marko Mikulicic 0:c0ecb8bf28eb 8362 0x1e33, 499, /* ḳ Ḳ */
Marko Mikulicic 0:c0ecb8bf28eb 8363 0x1e35, 499, /* ḵ Ḵ */
Marko Mikulicic 0:c0ecb8bf28eb 8364 0x1e37, 499, /* ḷ Ḷ */
Marko Mikulicic 0:c0ecb8bf28eb 8365 0x1e39, 499, /* ḹ Ḹ */
Marko Mikulicic 0:c0ecb8bf28eb 8366 0x1e3b, 499, /* ḻ Ḻ */
Marko Mikulicic 0:c0ecb8bf28eb 8367 0x1e3d, 499, /* ḽ Ḽ */
Marko Mikulicic 0:c0ecb8bf28eb 8368 0x1e3f, 499, /* ḿ Ḿ */
Marko Mikulicic 0:c0ecb8bf28eb 8369 0x1e41, 499, /* ṁ Ṁ */
Marko Mikulicic 0:c0ecb8bf28eb 8370 0x1e43, 499, /* ṃ Ṃ */
Marko Mikulicic 0:c0ecb8bf28eb 8371 0x1e45, 499, /* ṅ Ṅ */
Marko Mikulicic 0:c0ecb8bf28eb 8372 0x1e47, 499, /* ṇ Ṇ */
Marko Mikulicic 0:c0ecb8bf28eb 8373 0x1e49, 499, /* ṉ Ṉ */
Marko Mikulicic 0:c0ecb8bf28eb 8374 0x1e4b, 499, /* ṋ Ṋ */
Marko Mikulicic 0:c0ecb8bf28eb 8375 0x1e4d, 499, /* ṍ Ṍ */
Marko Mikulicic 0:c0ecb8bf28eb 8376 0x1e4f, 499, /* ṏ Ṏ */
Marko Mikulicic 0:c0ecb8bf28eb 8377 0x1e51, 499, /* ṑ Ṑ */
Marko Mikulicic 0:c0ecb8bf28eb 8378 0x1e53, 499, /* ṓ Ṓ */
Marko Mikulicic 0:c0ecb8bf28eb 8379 0x1e55, 499, /* ṕ Ṕ */
Marko Mikulicic 0:c0ecb8bf28eb 8380 0x1e57, 499, /* ṗ Ṗ */
Marko Mikulicic 0:c0ecb8bf28eb 8381 0x1e59, 499, /* ṙ Ṙ */
Marko Mikulicic 0:c0ecb8bf28eb 8382 0x1e5b, 499, /* ṛ Ṛ */
Marko Mikulicic 0:c0ecb8bf28eb 8383 0x1e5d, 499, /* ṝ Ṝ */
Marko Mikulicic 0:c0ecb8bf28eb 8384 0x1e5f, 499, /* ṟ Ṟ */
Marko Mikulicic 0:c0ecb8bf28eb 8385 0x1e61, 499, /* ṡ Ṡ */
Marko Mikulicic 0:c0ecb8bf28eb 8386 0x1e63, 499, /* ṣ Ṣ */
Marko Mikulicic 0:c0ecb8bf28eb 8387 0x1e65, 499, /* ṥ Ṥ */
Marko Mikulicic 0:c0ecb8bf28eb 8388 0x1e67, 499, /* ṧ Ṧ */
Marko Mikulicic 0:c0ecb8bf28eb 8389 0x1e69, 499, /* ṩ Ṩ */
Marko Mikulicic 0:c0ecb8bf28eb 8390 0x1e6b, 499, /* ṫ Ṫ */
Marko Mikulicic 0:c0ecb8bf28eb 8391 0x1e6d, 499, /* ṭ Ṭ */
Marko Mikulicic 0:c0ecb8bf28eb 8392 0x1e6f, 499, /* ṯ Ṯ */
Marko Mikulicic 0:c0ecb8bf28eb 8393 0x1e71, 499, /* ṱ Ṱ */
Marko Mikulicic 0:c0ecb8bf28eb 8394 0x1e73, 499, /* ṳ Ṳ */
Marko Mikulicic 0:c0ecb8bf28eb 8395 0x1e75, 499, /* ṵ Ṵ */
Marko Mikulicic 0:c0ecb8bf28eb 8396 0x1e77, 499, /* ṷ Ṷ */
Marko Mikulicic 0:c0ecb8bf28eb 8397 0x1e79, 499, /* ṹ Ṹ */
Marko Mikulicic 0:c0ecb8bf28eb 8398 0x1e7b, 499, /* ṻ Ṻ */
Marko Mikulicic 0:c0ecb8bf28eb 8399 0x1e7d, 499, /* ṽ Ṽ */
Marko Mikulicic 0:c0ecb8bf28eb 8400 0x1e7f, 499, /* ṿ Ṿ */
Marko Mikulicic 0:c0ecb8bf28eb 8401 0x1e81, 499, /* ẁ Ẁ */
Marko Mikulicic 0:c0ecb8bf28eb 8402 0x1e83, 499, /* ẃ Ẃ */
Marko Mikulicic 0:c0ecb8bf28eb 8403 0x1e85, 499, /* ẅ Ẅ */
Marko Mikulicic 0:c0ecb8bf28eb 8404 0x1e87, 499, /* ẇ Ẇ */
Marko Mikulicic 0:c0ecb8bf28eb 8405 0x1e89, 499, /* ẉ Ẉ */
Marko Mikulicic 0:c0ecb8bf28eb 8406 0x1e8b, 499, /* ẋ Ẋ */
Marko Mikulicic 0:c0ecb8bf28eb 8407 0x1e8d, 499, /* ẍ Ẍ */
Marko Mikulicic 0:c0ecb8bf28eb 8408 0x1e8f, 499, /* ẏ Ẏ */
Marko Mikulicic 0:c0ecb8bf28eb 8409 0x1e91, 499, /* ẑ Ẑ */
Marko Mikulicic 0:c0ecb8bf28eb 8410 0x1e93, 499, /* ẓ Ẓ */
Marko Mikulicic 0:c0ecb8bf28eb 8411 0x1e95, 499, /* ẕ Ẕ */
Marko Mikulicic 0:c0ecb8bf28eb 8412 0x1ea1, 499, /* ạ Ạ */
Marko Mikulicic 0:c0ecb8bf28eb 8413 0x1ea3, 499, /* ả Ả */
Marko Mikulicic 0:c0ecb8bf28eb 8414 0x1ea5, 499, /* ấ Ấ */
Marko Mikulicic 0:c0ecb8bf28eb 8415 0x1ea7, 499, /* ầ Ầ */
Marko Mikulicic 0:c0ecb8bf28eb 8416 0x1ea9, 499, /* ẩ Ẩ */
Marko Mikulicic 0:c0ecb8bf28eb 8417 0x1eab, 499, /* ẫ Ẫ */
Marko Mikulicic 0:c0ecb8bf28eb 8418 0x1ead, 499, /* ậ Ậ */
Marko Mikulicic 0:c0ecb8bf28eb 8419 0x1eaf, 499, /* ắ Ắ */
Marko Mikulicic 0:c0ecb8bf28eb 8420 0x1eb1, 499, /* ằ Ằ */
Marko Mikulicic 0:c0ecb8bf28eb 8421 0x1eb3, 499, /* ẳ Ẳ */
Marko Mikulicic 0:c0ecb8bf28eb 8422 0x1eb5, 499, /* ẵ Ẵ */
Marko Mikulicic 0:c0ecb8bf28eb 8423 0x1eb7, 499, /* ặ Ặ */
Marko Mikulicic 0:c0ecb8bf28eb 8424 0x1eb9, 499, /* ẹ Ẹ */
Marko Mikulicic 0:c0ecb8bf28eb 8425 0x1ebb, 499, /* ẻ Ẻ */
Marko Mikulicic 0:c0ecb8bf28eb 8426 0x1ebd, 499, /* ẽ Ẽ */
Marko Mikulicic 0:c0ecb8bf28eb 8427 0x1ebf, 499, /* ế Ế */
Marko Mikulicic 0:c0ecb8bf28eb 8428 0x1ec1, 499, /* ề Ề */
Marko Mikulicic 0:c0ecb8bf28eb 8429 0x1ec3, 499, /* ể Ể */
Marko Mikulicic 0:c0ecb8bf28eb 8430 0x1ec5, 499, /* ễ Ễ */
Marko Mikulicic 0:c0ecb8bf28eb 8431 0x1ec7, 499, /* ệ Ệ */
Marko Mikulicic 0:c0ecb8bf28eb 8432 0x1ec9, 499, /* ỉ Ỉ */
Marko Mikulicic 0:c0ecb8bf28eb 8433 0x1ecb, 499, /* ị Ị */
Marko Mikulicic 0:c0ecb8bf28eb 8434 0x1ecd, 499, /* ọ Ọ */
Marko Mikulicic 0:c0ecb8bf28eb 8435 0x1ecf, 499, /* ỏ Ỏ */
Marko Mikulicic 0:c0ecb8bf28eb 8436 0x1ed1, 499, /* ố Ố */
Marko Mikulicic 0:c0ecb8bf28eb 8437 0x1ed3, 499, /* ồ Ồ */
Marko Mikulicic 0:c0ecb8bf28eb 8438 0x1ed5, 499, /* ổ Ổ */
Marko Mikulicic 0:c0ecb8bf28eb 8439 0x1ed7, 499, /* ỗ Ỗ */
Marko Mikulicic 0:c0ecb8bf28eb 8440 0x1ed9, 499, /* ộ Ộ */
Marko Mikulicic 0:c0ecb8bf28eb 8441 0x1edb, 499, /* ớ Ớ */
Marko Mikulicic 0:c0ecb8bf28eb 8442 0x1edd, 499, /* ờ Ờ */
Marko Mikulicic 0:c0ecb8bf28eb 8443 0x1edf, 499, /* ở Ở */
Marko Mikulicic 0:c0ecb8bf28eb 8444 0x1ee1, 499, /* ỡ Ỡ */
Marko Mikulicic 0:c0ecb8bf28eb 8445 0x1ee3, 499, /* ợ Ợ */
Marko Mikulicic 0:c0ecb8bf28eb 8446 0x1ee5, 499, /* ụ Ụ */
Marko Mikulicic 0:c0ecb8bf28eb 8447 0x1ee7, 499, /* ủ Ủ */
Marko Mikulicic 0:c0ecb8bf28eb 8448 0x1ee9, 499, /* ứ Ứ */
Marko Mikulicic 0:c0ecb8bf28eb 8449 0x1eeb, 499, /* ừ Ừ */
Marko Mikulicic 0:c0ecb8bf28eb 8450 0x1eed, 499, /* ử Ử */
Marko Mikulicic 0:c0ecb8bf28eb 8451 0x1eef, 499, /* ữ Ữ */
Marko Mikulicic 0:c0ecb8bf28eb 8452 0x1ef1, 499, /* ự Ự */
Marko Mikulicic 0:c0ecb8bf28eb 8453 0x1ef3, 499, /* ỳ Ỳ */
Marko Mikulicic 0:c0ecb8bf28eb 8454 0x1ef5, 499, /* ỵ Ỵ */
Marko Mikulicic 0:c0ecb8bf28eb 8455 0x1ef7, 499, /* ỷ Ỷ */
Marko Mikulicic 0:c0ecb8bf28eb 8456 0x1ef9, 499, /* ỹ Ỹ */
Marko Mikulicic 0:c0ecb8bf28eb 8457 0x1f51, 508, /* ὑ Ὑ */
Marko Mikulicic 0:c0ecb8bf28eb 8458 0x1f53, 508, /* ὓ Ὓ */
Marko Mikulicic 0:c0ecb8bf28eb 8459 0x1f55, 508, /* ὕ Ὕ */
Marko Mikulicic 0:c0ecb8bf28eb 8460 0x1f57, 508, /* ὗ Ὗ */
Marko Mikulicic 0:c0ecb8bf28eb 8461 0x1fb3, 509, /* ᾳ ᾼ */
Marko Mikulicic 0:c0ecb8bf28eb 8462 0x1fc3, 509, /* ῃ ῌ */
Marko Mikulicic 0:c0ecb8bf28eb 8463 0x1fe5, 507, /* ῥ Ῥ */
Marko Mikulicic 0:c0ecb8bf28eb 8464 0x1ff3, 509, /* ῳ ῼ */
Marko Mikulicic 0:c0ecb8bf28eb 8465 };
Marko Mikulicic 0:c0ecb8bf28eb 8466
Marko Mikulicic 0:c0ecb8bf28eb 8467 /*
Marko Mikulicic 0:c0ecb8bf28eb 8468 * upper case ranges
Marko Mikulicic 0:c0ecb8bf28eb 8469 * 3rd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8470 */
Marko Mikulicic 0:c0ecb8bf28eb 8471 static Rune __tolower2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8472 0x0041, 0x005a, 532, /* A-Z a-z */
Marko Mikulicic 0:c0ecb8bf28eb 8473 0x00c0, 0x00d6, 532, /* À-Ö à-ö */
Marko Mikulicic 0:c0ecb8bf28eb 8474 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */
Marko Mikulicic 0:c0ecb8bf28eb 8475 0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */
Marko Mikulicic 0:c0ecb8bf28eb 8476 0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */
Marko Mikulicic 0:c0ecb8bf28eb 8477 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */
Marko Mikulicic 0:c0ecb8bf28eb 8478 0x0388, 0x038a, 537, /* Έ-Ί έ-ί */
Marko Mikulicic 0:c0ecb8bf28eb 8479 0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8480 0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */
Marko Mikulicic 0:c0ecb8bf28eb 8481 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */
Marko Mikulicic 0:c0ecb8bf28eb 8482 0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */
Marko Mikulicic 0:c0ecb8bf28eb 8483 0x040e, 0x040f, 580, /* Ў-Џ ў-џ */
Marko Mikulicic 0:c0ecb8bf28eb 8484 0x0410, 0x042f, 532, /* А-Я а-я */
Marko Mikulicic 0:c0ecb8bf28eb 8485 0x0531, 0x0556, 548, /* Ա-Ֆ ա-ֆ */
Marko Mikulicic 0:c0ecb8bf28eb 8486 0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */
Marko Mikulicic 0:c0ecb8bf28eb 8487 0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */
Marko Mikulicic 0:c0ecb8bf28eb 8488 0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */
Marko Mikulicic 0:c0ecb8bf28eb 8489 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */
Marko Mikulicic 0:c0ecb8bf28eb 8490 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */
Marko Mikulicic 0:c0ecb8bf28eb 8491 0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */
Marko Mikulicic 0:c0ecb8bf28eb 8492 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */
Marko Mikulicic 0:c0ecb8bf28eb 8493 0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */
Marko Mikulicic 0:c0ecb8bf28eb 8494 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */
Marko Mikulicic 0:c0ecb8bf28eb 8495 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */
Marko Mikulicic 0:c0ecb8bf28eb 8496 0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */
Marko Mikulicic 0:c0ecb8bf28eb 8497 0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */
Marko Mikulicic 0:c0ecb8bf28eb 8498 0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */
Marko Mikulicic 0:c0ecb8bf28eb 8499 0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */
Marko Mikulicic 0:c0ecb8bf28eb 8500 0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */
Marko Mikulicic 0:c0ecb8bf28eb 8501 0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */
Marko Mikulicic 0:c0ecb8bf28eb 8502 0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */
Marko Mikulicic 0:c0ecb8bf28eb 8503 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */
Marko Mikulicic 0:c0ecb8bf28eb 8504 0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8505 0x2160, 0x216f, 516, /* Ⅰ-Ⅿ ⅰ-ⅿ */
Marko Mikulicic 0:c0ecb8bf28eb 8506 0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */
Marko Mikulicic 0:c0ecb8bf28eb 8507 0xff21, 0xff3a, 532, /* A-Z a-z */
Marko Mikulicic 0:c0ecb8bf28eb 8508 };
Marko Mikulicic 0:c0ecb8bf28eb 8509
Marko Mikulicic 0:c0ecb8bf28eb 8510 /*
Marko Mikulicic 0:c0ecb8bf28eb 8511 * upper case singlets
Marko Mikulicic 0:c0ecb8bf28eb 8512 * 2nd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8513 */
Marko Mikulicic 0:c0ecb8bf28eb 8514 static Rune __tolower1[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8515 0x0100, 501, /* Ā ā */
Marko Mikulicic 0:c0ecb8bf28eb 8516 0x0102, 501, /* Ă ă */
Marko Mikulicic 0:c0ecb8bf28eb 8517 0x0104, 501, /* Ą ą */
Marko Mikulicic 0:c0ecb8bf28eb 8518 0x0106, 501, /* Ć ć */
Marko Mikulicic 0:c0ecb8bf28eb 8519 0x0108, 501, /* Ĉ ĉ */
Marko Mikulicic 0:c0ecb8bf28eb 8520 0x010a, 501, /* Ċ ċ */
Marko Mikulicic 0:c0ecb8bf28eb 8521 0x010c, 501, /* Č č */
Marko Mikulicic 0:c0ecb8bf28eb 8522 0x010e, 501, /* Ď ď */
Marko Mikulicic 0:c0ecb8bf28eb 8523 0x0110, 501, /* Đ đ */
Marko Mikulicic 0:c0ecb8bf28eb 8524 0x0112, 501, /* Ē ē */
Marko Mikulicic 0:c0ecb8bf28eb 8525 0x0114, 501, /* Ĕ ĕ */
Marko Mikulicic 0:c0ecb8bf28eb 8526 0x0116, 501, /* Ė ė */
Marko Mikulicic 0:c0ecb8bf28eb 8527 0x0118, 501, /* Ę ę */
Marko Mikulicic 0:c0ecb8bf28eb 8528 0x011a, 501, /* Ě ě */
Marko Mikulicic 0:c0ecb8bf28eb 8529 0x011c, 501, /* Ĝ ĝ */
Marko Mikulicic 0:c0ecb8bf28eb 8530 0x011e, 501, /* Ğ ğ */
Marko Mikulicic 0:c0ecb8bf28eb 8531 0x0120, 501, /* Ġ ġ */
Marko Mikulicic 0:c0ecb8bf28eb 8532 0x0122, 501, /* Ģ ģ */
Marko Mikulicic 0:c0ecb8bf28eb 8533 0x0124, 501, /* Ĥ ĥ */
Marko Mikulicic 0:c0ecb8bf28eb 8534 0x0126, 501, /* Ħ ħ */
Marko Mikulicic 0:c0ecb8bf28eb 8535 0x0128, 501, /* Ĩ ĩ */
Marko Mikulicic 0:c0ecb8bf28eb 8536 0x012a, 501, /* Ī ī */
Marko Mikulicic 0:c0ecb8bf28eb 8537 0x012c, 501, /* Ĭ ĭ */
Marko Mikulicic 0:c0ecb8bf28eb 8538 0x012e, 501, /* Į į */
Marko Mikulicic 0:c0ecb8bf28eb 8539 0x0130, 301, /* İ i */
Marko Mikulicic 0:c0ecb8bf28eb 8540 0x0132, 501, /* IJ ij */
Marko Mikulicic 0:c0ecb8bf28eb 8541 0x0134, 501, /* Ĵ ĵ */
Marko Mikulicic 0:c0ecb8bf28eb 8542 0x0136, 501, /* Ķ ķ */
Marko Mikulicic 0:c0ecb8bf28eb 8543 0x0139, 501, /* Ĺ ĺ */
Marko Mikulicic 0:c0ecb8bf28eb 8544 0x013b, 501, /* Ļ ļ */
Marko Mikulicic 0:c0ecb8bf28eb 8545 0x013d, 501, /* Ľ ľ */
Marko Mikulicic 0:c0ecb8bf28eb 8546 0x013f, 501, /* Ŀ ŀ */
Marko Mikulicic 0:c0ecb8bf28eb 8547 0x0141, 501, /* Ł ł */
Marko Mikulicic 0:c0ecb8bf28eb 8548 0x0143, 501, /* Ń ń */
Marko Mikulicic 0:c0ecb8bf28eb 8549 0x0145, 501, /* Ņ ņ */
Marko Mikulicic 0:c0ecb8bf28eb 8550 0x0147, 501, /* Ň ň */
Marko Mikulicic 0:c0ecb8bf28eb 8551 0x014a, 501, /* Ŋ ŋ */
Marko Mikulicic 0:c0ecb8bf28eb 8552 0x014c, 501, /* Ō ō */
Marko Mikulicic 0:c0ecb8bf28eb 8553 0x014e, 501, /* Ŏ ŏ */
Marko Mikulicic 0:c0ecb8bf28eb 8554 0x0150, 501, /* Ő ő */
Marko Mikulicic 0:c0ecb8bf28eb 8555 0x0152, 501, /* Œ œ */
Marko Mikulicic 0:c0ecb8bf28eb 8556 0x0154, 501, /* Ŕ ŕ */
Marko Mikulicic 0:c0ecb8bf28eb 8557 0x0156, 501, /* Ŗ ŗ */
Marko Mikulicic 0:c0ecb8bf28eb 8558 0x0158, 501, /* Ř ř */
Marko Mikulicic 0:c0ecb8bf28eb 8559 0x015a, 501, /* Ś ś */
Marko Mikulicic 0:c0ecb8bf28eb 8560 0x015c, 501, /* Ŝ ŝ */
Marko Mikulicic 0:c0ecb8bf28eb 8561 0x015e, 501, /* Ş ş */
Marko Mikulicic 0:c0ecb8bf28eb 8562 0x0160, 501, /* Š š */
Marko Mikulicic 0:c0ecb8bf28eb 8563 0x0162, 501, /* Ţ ţ */
Marko Mikulicic 0:c0ecb8bf28eb 8564 0x0164, 501, /* Ť ť */
Marko Mikulicic 0:c0ecb8bf28eb 8565 0x0166, 501, /* Ŧ ŧ */
Marko Mikulicic 0:c0ecb8bf28eb 8566 0x0168, 501, /* Ũ ũ */
Marko Mikulicic 0:c0ecb8bf28eb 8567 0x016a, 501, /* Ū ū */
Marko Mikulicic 0:c0ecb8bf28eb 8568 0x016c, 501, /* Ŭ ŭ */
Marko Mikulicic 0:c0ecb8bf28eb 8569 0x016e, 501, /* Ů ů */
Marko Mikulicic 0:c0ecb8bf28eb 8570 0x0170, 501, /* Ű ű */
Marko Mikulicic 0:c0ecb8bf28eb 8571 0x0172, 501, /* Ų ų */
Marko Mikulicic 0:c0ecb8bf28eb 8572 0x0174, 501, /* Ŵ ŵ */
Marko Mikulicic 0:c0ecb8bf28eb 8573 0x0176, 501, /* Ŷ ŷ */
Marko Mikulicic 0:c0ecb8bf28eb 8574 0x0178, 379, /* Ÿ ÿ */
Marko Mikulicic 0:c0ecb8bf28eb 8575 0x0179, 501, /* Ź ź */
Marko Mikulicic 0:c0ecb8bf28eb 8576 0x017b, 501, /* Ż ż */
Marko Mikulicic 0:c0ecb8bf28eb 8577 0x017d, 501, /* Ž ž */
Marko Mikulicic 0:c0ecb8bf28eb 8578 0x0181, 710, /* Ɓ ɓ */
Marko Mikulicic 0:c0ecb8bf28eb 8579 0x0182, 501, /* Ƃ ƃ */
Marko Mikulicic 0:c0ecb8bf28eb 8580 0x0184, 501, /* Ƅ ƅ */
Marko Mikulicic 0:c0ecb8bf28eb 8581 0x0186, 706, /* Ɔ ɔ */
Marko Mikulicic 0:c0ecb8bf28eb 8582 0x0187, 501, /* Ƈ ƈ */
Marko Mikulicic 0:c0ecb8bf28eb 8583 0x018b, 501, /* Ƌ ƌ */
Marko Mikulicic 0:c0ecb8bf28eb 8584 0x0190, 703, /* Ɛ ɛ */
Marko Mikulicic 0:c0ecb8bf28eb 8585 0x0191, 501, /* Ƒ ƒ */
Marko Mikulicic 0:c0ecb8bf28eb 8586 0x0193, 705, /* Ɠ ɠ */
Marko Mikulicic 0:c0ecb8bf28eb 8587 0x0194, 707, /* Ɣ ɣ */
Marko Mikulicic 0:c0ecb8bf28eb 8588 0x0196, 711, /* Ɩ ɩ */
Marko Mikulicic 0:c0ecb8bf28eb 8589 0x0197, 709, /* Ɨ ɨ */
Marko Mikulicic 0:c0ecb8bf28eb 8590 0x0198, 501, /* Ƙ ƙ */
Marko Mikulicic 0:c0ecb8bf28eb 8591 0x019c, 711, /* Ɯ ɯ */
Marko Mikulicic 0:c0ecb8bf28eb 8592 0x019d, 713, /* Ɲ ɲ */
Marko Mikulicic 0:c0ecb8bf28eb 8593 0x01a0, 501, /* Ơ ơ */
Marko Mikulicic 0:c0ecb8bf28eb 8594 0x01a2, 501, /* Ƣ ƣ */
Marko Mikulicic 0:c0ecb8bf28eb 8595 0x01a4, 501, /* Ƥ ƥ */
Marko Mikulicic 0:c0ecb8bf28eb 8596 0x01a7, 501, /* Ƨ ƨ */
Marko Mikulicic 0:c0ecb8bf28eb 8597 0x01a9, 718, /* Ʃ ʃ */
Marko Mikulicic 0:c0ecb8bf28eb 8598 0x01ac, 501, /* Ƭ ƭ */
Marko Mikulicic 0:c0ecb8bf28eb 8599 0x01ae, 718, /* Ʈ ʈ */
Marko Mikulicic 0:c0ecb8bf28eb 8600 0x01af, 501, /* Ư ư */
Marko Mikulicic 0:c0ecb8bf28eb 8601 0x01b3, 501, /* Ƴ ƴ */
Marko Mikulicic 0:c0ecb8bf28eb 8602 0x01b5, 501, /* Ƶ ƶ */
Marko Mikulicic 0:c0ecb8bf28eb 8603 0x01b7, 719, /* Ʒ ʒ */
Marko Mikulicic 0:c0ecb8bf28eb 8604 0x01b8, 501, /* Ƹ ƹ */
Marko Mikulicic 0:c0ecb8bf28eb 8605 0x01bc, 501, /* Ƽ ƽ */
Marko Mikulicic 0:c0ecb8bf28eb 8606 0x01c4, 502, /* DŽ dž */
Marko Mikulicic 0:c0ecb8bf28eb 8607 0x01c5, 501, /* Dž dž */
Marko Mikulicic 0:c0ecb8bf28eb 8608 0x01c7, 502, /* LJ lj */
Marko Mikulicic 0:c0ecb8bf28eb 8609 0x01c8, 501, /* Lj lj */
Marko Mikulicic 0:c0ecb8bf28eb 8610 0x01ca, 502, /* NJ nj */
Marko Mikulicic 0:c0ecb8bf28eb 8611 0x01cb, 501, /* Nj nj */
Marko Mikulicic 0:c0ecb8bf28eb 8612 0x01cd, 501, /* Ǎ ǎ */
Marko Mikulicic 0:c0ecb8bf28eb 8613 0x01cf, 501, /* Ǐ ǐ */
Marko Mikulicic 0:c0ecb8bf28eb 8614 0x01d1, 501, /* Ǒ ǒ */
Marko Mikulicic 0:c0ecb8bf28eb 8615 0x01d3, 501, /* Ǔ ǔ */
Marko Mikulicic 0:c0ecb8bf28eb 8616 0x01d5, 501, /* Ǖ ǖ */
Marko Mikulicic 0:c0ecb8bf28eb 8617 0x01d7, 501, /* Ǘ ǘ */
Marko Mikulicic 0:c0ecb8bf28eb 8618 0x01d9, 501, /* Ǚ ǚ */
Marko Mikulicic 0:c0ecb8bf28eb 8619 0x01db, 501, /* Ǜ ǜ */
Marko Mikulicic 0:c0ecb8bf28eb 8620 0x01de, 501, /* Ǟ ǟ */
Marko Mikulicic 0:c0ecb8bf28eb 8621 0x01e0, 501, /* Ǡ ǡ */
Marko Mikulicic 0:c0ecb8bf28eb 8622 0x01e2, 501, /* Ǣ ǣ */
Marko Mikulicic 0:c0ecb8bf28eb 8623 0x01e4, 501, /* Ǥ ǥ */
Marko Mikulicic 0:c0ecb8bf28eb 8624 0x01e6, 501, /* Ǧ ǧ */
Marko Mikulicic 0:c0ecb8bf28eb 8625 0x01e8, 501, /* Ǩ ǩ */
Marko Mikulicic 0:c0ecb8bf28eb 8626 0x01ea, 501, /* Ǫ ǫ */
Marko Mikulicic 0:c0ecb8bf28eb 8627 0x01ec, 501, /* Ǭ ǭ */
Marko Mikulicic 0:c0ecb8bf28eb 8628 0x01ee, 501, /* Ǯ ǯ */
Marko Mikulicic 0:c0ecb8bf28eb 8629 0x01f1, 502, /* DZ dz */
Marko Mikulicic 0:c0ecb8bf28eb 8630 0x01f2, 501, /* Dz dz */
Marko Mikulicic 0:c0ecb8bf28eb 8631 0x01f4, 501, /* Ǵ ǵ */
Marko Mikulicic 0:c0ecb8bf28eb 8632 0x01fa, 501, /* Ǻ ǻ */
Marko Mikulicic 0:c0ecb8bf28eb 8633 0x01fc, 501, /* Ǽ ǽ */
Marko Mikulicic 0:c0ecb8bf28eb 8634 0x01fe, 501, /* Ǿ ǿ */
Marko Mikulicic 0:c0ecb8bf28eb 8635 0x0200, 501, /* Ȁ ȁ */
Marko Mikulicic 0:c0ecb8bf28eb 8636 0x0202, 501, /* Ȃ ȃ */
Marko Mikulicic 0:c0ecb8bf28eb 8637 0x0204, 501, /* Ȅ ȅ */
Marko Mikulicic 0:c0ecb8bf28eb 8638 0x0206, 501, /* Ȇ ȇ */
Marko Mikulicic 0:c0ecb8bf28eb 8639 0x0208, 501, /* Ȉ ȉ */
Marko Mikulicic 0:c0ecb8bf28eb 8640 0x020a, 501, /* Ȋ ȋ */
Marko Mikulicic 0:c0ecb8bf28eb 8641 0x020c, 501, /* Ȍ ȍ */
Marko Mikulicic 0:c0ecb8bf28eb 8642 0x020e, 501, /* Ȏ ȏ */
Marko Mikulicic 0:c0ecb8bf28eb 8643 0x0210, 501, /* Ȑ ȑ */
Marko Mikulicic 0:c0ecb8bf28eb 8644 0x0212, 501, /* Ȓ ȓ */
Marko Mikulicic 0:c0ecb8bf28eb 8645 0x0214, 501, /* Ȕ ȕ */
Marko Mikulicic 0:c0ecb8bf28eb 8646 0x0216, 501, /* Ȗ ȗ */
Marko Mikulicic 0:c0ecb8bf28eb 8647 0x0386, 538, /* Ά ά */
Marko Mikulicic 0:c0ecb8bf28eb 8648 0x038c, 564, /* Ό ό */
Marko Mikulicic 0:c0ecb8bf28eb 8649 0x03e2, 501, /* Ϣ ϣ */
Marko Mikulicic 0:c0ecb8bf28eb 8650 0x03e4, 501, /* Ϥ ϥ */
Marko Mikulicic 0:c0ecb8bf28eb 8651 0x03e6, 501, /* Ϧ ϧ */
Marko Mikulicic 0:c0ecb8bf28eb 8652 0x03e8, 501, /* Ϩ ϩ */
Marko Mikulicic 0:c0ecb8bf28eb 8653 0x03ea, 501, /* Ϫ ϫ */
Marko Mikulicic 0:c0ecb8bf28eb 8654 0x03ec, 501, /* Ϭ ϭ */
Marko Mikulicic 0:c0ecb8bf28eb 8655 0x03ee, 501, /* Ϯ ϯ */
Marko Mikulicic 0:c0ecb8bf28eb 8656 0x0460, 501, /* Ѡ ѡ */
Marko Mikulicic 0:c0ecb8bf28eb 8657 0x0462, 501, /* Ѣ ѣ */
Marko Mikulicic 0:c0ecb8bf28eb 8658 0x0464, 501, /* Ѥ ѥ */
Marko Mikulicic 0:c0ecb8bf28eb 8659 0x0466, 501, /* Ѧ ѧ */
Marko Mikulicic 0:c0ecb8bf28eb 8660 0x0468, 501, /* Ѩ ѩ */
Marko Mikulicic 0:c0ecb8bf28eb 8661 0x046a, 501, /* Ѫ ѫ */
Marko Mikulicic 0:c0ecb8bf28eb 8662 0x046c, 501, /* Ѭ ѭ */
Marko Mikulicic 0:c0ecb8bf28eb 8663 0x046e, 501, /* Ѯ ѯ */
Marko Mikulicic 0:c0ecb8bf28eb 8664 0x0470, 501, /* Ѱ ѱ */
Marko Mikulicic 0:c0ecb8bf28eb 8665 0x0472, 501, /* Ѳ ѳ */
Marko Mikulicic 0:c0ecb8bf28eb 8666 0x0474, 501, /* Ѵ ѵ */
Marko Mikulicic 0:c0ecb8bf28eb 8667 0x0476, 501, /* Ѷ ѷ */
Marko Mikulicic 0:c0ecb8bf28eb 8668 0x0478, 501, /* Ѹ ѹ */
Marko Mikulicic 0:c0ecb8bf28eb 8669 0x047a, 501, /* Ѻ ѻ */
Marko Mikulicic 0:c0ecb8bf28eb 8670 0x047c, 501, /* Ѽ ѽ */
Marko Mikulicic 0:c0ecb8bf28eb 8671 0x047e, 501, /* Ѿ ѿ */
Marko Mikulicic 0:c0ecb8bf28eb 8672 0x0480, 501, /* Ҁ ҁ */
Marko Mikulicic 0:c0ecb8bf28eb 8673 0x0490, 501, /* Ґ ґ */
Marko Mikulicic 0:c0ecb8bf28eb 8674 0x0492, 501, /* Ғ ғ */
Marko Mikulicic 0:c0ecb8bf28eb 8675 0x0494, 501, /* Ҕ ҕ */
Marko Mikulicic 0:c0ecb8bf28eb 8676 0x0496, 501, /* Җ җ */
Marko Mikulicic 0:c0ecb8bf28eb 8677 0x0498, 501, /* Ҙ ҙ */
Marko Mikulicic 0:c0ecb8bf28eb 8678 0x049a, 501, /* Қ қ */
Marko Mikulicic 0:c0ecb8bf28eb 8679 0x049c, 501, /* Ҝ ҝ */
Marko Mikulicic 0:c0ecb8bf28eb 8680 0x049e, 501, /* Ҟ ҟ */
Marko Mikulicic 0:c0ecb8bf28eb 8681 0x04a0, 501, /* Ҡ ҡ */
Marko Mikulicic 0:c0ecb8bf28eb 8682 0x04a2, 501, /* Ң ң */
Marko Mikulicic 0:c0ecb8bf28eb 8683 0x04a4, 501, /* Ҥ ҥ */
Marko Mikulicic 0:c0ecb8bf28eb 8684 0x04a6, 501, /* Ҧ ҧ */
Marko Mikulicic 0:c0ecb8bf28eb 8685 0x04a8, 501, /* Ҩ ҩ */
Marko Mikulicic 0:c0ecb8bf28eb 8686 0x04aa, 501, /* Ҫ ҫ */
Marko Mikulicic 0:c0ecb8bf28eb 8687 0x04ac, 501, /* Ҭ ҭ */
Marko Mikulicic 0:c0ecb8bf28eb 8688 0x04ae, 501, /* Ү ү */
Marko Mikulicic 0:c0ecb8bf28eb 8689 0x04b0, 501, /* Ұ ұ */
Marko Mikulicic 0:c0ecb8bf28eb 8690 0x04b2, 501, /* Ҳ ҳ */
Marko Mikulicic 0:c0ecb8bf28eb 8691 0x04b4, 501, /* Ҵ ҵ */
Marko Mikulicic 0:c0ecb8bf28eb 8692 0x04b6, 501, /* Ҷ ҷ */
Marko Mikulicic 0:c0ecb8bf28eb 8693 0x04b8, 501, /* Ҹ ҹ */
Marko Mikulicic 0:c0ecb8bf28eb 8694 0x04ba, 501, /* Һ һ */
Marko Mikulicic 0:c0ecb8bf28eb 8695 0x04bc, 501, /* Ҽ ҽ */
Marko Mikulicic 0:c0ecb8bf28eb 8696 0x04be, 501, /* Ҿ ҿ */
Marko Mikulicic 0:c0ecb8bf28eb 8697 0x04c1, 501, /* Ӂ ӂ */
Marko Mikulicic 0:c0ecb8bf28eb 8698 0x04c3, 501, /* Ӄ ӄ */
Marko Mikulicic 0:c0ecb8bf28eb 8699 0x04c7, 501, /* Ӈ ӈ */
Marko Mikulicic 0:c0ecb8bf28eb 8700 0x04cb, 501, /* Ӌ ӌ */
Marko Mikulicic 0:c0ecb8bf28eb 8701 0x04d0, 501, /* Ӑ ӑ */
Marko Mikulicic 0:c0ecb8bf28eb 8702 0x04d2, 501, /* Ӓ ӓ */
Marko Mikulicic 0:c0ecb8bf28eb 8703 0x04d4, 501, /* Ӕ ӕ */
Marko Mikulicic 0:c0ecb8bf28eb 8704 0x04d6, 501, /* Ӗ ӗ */
Marko Mikulicic 0:c0ecb8bf28eb 8705 0x04d8, 501, /* Ә ә */
Marko Mikulicic 0:c0ecb8bf28eb 8706 0x04da, 501, /* Ӛ ӛ */
Marko Mikulicic 0:c0ecb8bf28eb 8707 0x04dc, 501, /* Ӝ ӝ */
Marko Mikulicic 0:c0ecb8bf28eb 8708 0x04de, 501, /* Ӟ ӟ */
Marko Mikulicic 0:c0ecb8bf28eb 8709 0x04e0, 501, /* Ӡ ӡ */
Marko Mikulicic 0:c0ecb8bf28eb 8710 0x04e2, 501, /* Ӣ ӣ */
Marko Mikulicic 0:c0ecb8bf28eb 8711 0x04e4, 501, /* Ӥ ӥ */
Marko Mikulicic 0:c0ecb8bf28eb 8712 0x04e6, 501, /* Ӧ ӧ */
Marko Mikulicic 0:c0ecb8bf28eb 8713 0x04e8, 501, /* Ө ө */
Marko Mikulicic 0:c0ecb8bf28eb 8714 0x04ea, 501, /* Ӫ ӫ */
Marko Mikulicic 0:c0ecb8bf28eb 8715 0x04ee, 501, /* Ӯ ӯ */
Marko Mikulicic 0:c0ecb8bf28eb 8716 0x04f0, 501, /* Ӱ ӱ */
Marko Mikulicic 0:c0ecb8bf28eb 8717 0x04f2, 501, /* Ӳ ӳ */
Marko Mikulicic 0:c0ecb8bf28eb 8718 0x04f4, 501, /* Ӵ ӵ */
Marko Mikulicic 0:c0ecb8bf28eb 8719 0x04f8, 501, /* Ӹ ӹ */
Marko Mikulicic 0:c0ecb8bf28eb 8720 0x1e00, 501, /* Ḁ ḁ */
Marko Mikulicic 0:c0ecb8bf28eb 8721 0x1e02, 501, /* Ḃ ḃ */
Marko Mikulicic 0:c0ecb8bf28eb 8722 0x1e04, 501, /* Ḅ ḅ */
Marko Mikulicic 0:c0ecb8bf28eb 8723 0x1e06, 501, /* Ḇ ḇ */
Marko Mikulicic 0:c0ecb8bf28eb 8724 0x1e08, 501, /* Ḉ ḉ */
Marko Mikulicic 0:c0ecb8bf28eb 8725 0x1e0a, 501, /* Ḋ ḋ */
Marko Mikulicic 0:c0ecb8bf28eb 8726 0x1e0c, 501, /* Ḍ ḍ */
Marko Mikulicic 0:c0ecb8bf28eb 8727 0x1e0e, 501, /* Ḏ ḏ */
Marko Mikulicic 0:c0ecb8bf28eb 8728 0x1e10, 501, /* Ḑ ḑ */
Marko Mikulicic 0:c0ecb8bf28eb 8729 0x1e12, 501, /* Ḓ ḓ */
Marko Mikulicic 0:c0ecb8bf28eb 8730 0x1e14, 501, /* Ḕ ḕ */
Marko Mikulicic 0:c0ecb8bf28eb 8731 0x1e16, 501, /* Ḗ ḗ */
Marko Mikulicic 0:c0ecb8bf28eb 8732 0x1e18, 501, /* Ḙ ḙ */
Marko Mikulicic 0:c0ecb8bf28eb 8733 0x1e1a, 501, /* Ḛ ḛ */
Marko Mikulicic 0:c0ecb8bf28eb 8734 0x1e1c, 501, /* Ḝ ḝ */
Marko Mikulicic 0:c0ecb8bf28eb 8735 0x1e1e, 501, /* Ḟ ḟ */
Marko Mikulicic 0:c0ecb8bf28eb 8736 0x1e20, 501, /* Ḡ ḡ */
Marko Mikulicic 0:c0ecb8bf28eb 8737 0x1e22, 501, /* Ḣ ḣ */
Marko Mikulicic 0:c0ecb8bf28eb 8738 0x1e24, 501, /* Ḥ ḥ */
Marko Mikulicic 0:c0ecb8bf28eb 8739 0x1e26, 501, /* Ḧ ḧ */
Marko Mikulicic 0:c0ecb8bf28eb 8740 0x1e28, 501, /* Ḩ ḩ */
Marko Mikulicic 0:c0ecb8bf28eb 8741 0x1e2a, 501, /* Ḫ ḫ */
Marko Mikulicic 0:c0ecb8bf28eb 8742 0x1e2c, 501, /* Ḭ ḭ */
Marko Mikulicic 0:c0ecb8bf28eb 8743 0x1e2e, 501, /* Ḯ ḯ */
Marko Mikulicic 0:c0ecb8bf28eb 8744 0x1e30, 501, /* Ḱ ḱ */
Marko Mikulicic 0:c0ecb8bf28eb 8745 0x1e32, 501, /* Ḳ ḳ */
Marko Mikulicic 0:c0ecb8bf28eb 8746 0x1e34, 501, /* Ḵ ḵ */
Marko Mikulicic 0:c0ecb8bf28eb 8747 0x1e36, 501, /* Ḷ ḷ */
Marko Mikulicic 0:c0ecb8bf28eb 8748 0x1e38, 501, /* Ḹ ḹ */
Marko Mikulicic 0:c0ecb8bf28eb 8749 0x1e3a, 501, /* Ḻ ḻ */
Marko Mikulicic 0:c0ecb8bf28eb 8750 0x1e3c, 501, /* Ḽ ḽ */
Marko Mikulicic 0:c0ecb8bf28eb 8751 0x1e3e, 501, /* Ḿ ḿ */
Marko Mikulicic 0:c0ecb8bf28eb 8752 0x1e40, 501, /* Ṁ ṁ */
Marko Mikulicic 0:c0ecb8bf28eb 8753 0x1e42, 501, /* Ṃ ṃ */
Marko Mikulicic 0:c0ecb8bf28eb 8754 0x1e44, 501, /* Ṅ ṅ */
Marko Mikulicic 0:c0ecb8bf28eb 8755 0x1e46, 501, /* Ṇ ṇ */
Marko Mikulicic 0:c0ecb8bf28eb 8756 0x1e48, 501, /* Ṉ ṉ */
Marko Mikulicic 0:c0ecb8bf28eb 8757 0x1e4a, 501, /* Ṋ ṋ */
Marko Mikulicic 0:c0ecb8bf28eb 8758 0x1e4c, 501, /* Ṍ ṍ */
Marko Mikulicic 0:c0ecb8bf28eb 8759 0x1e4e, 501, /* Ṏ ṏ */
Marko Mikulicic 0:c0ecb8bf28eb 8760 0x1e50, 501, /* Ṑ ṑ */
Marko Mikulicic 0:c0ecb8bf28eb 8761 0x1e52, 501, /* Ṓ ṓ */
Marko Mikulicic 0:c0ecb8bf28eb 8762 0x1e54, 501, /* Ṕ ṕ */
Marko Mikulicic 0:c0ecb8bf28eb 8763 0x1e56, 501, /* Ṗ ṗ */
Marko Mikulicic 0:c0ecb8bf28eb 8764 0x1e58, 501, /* Ṙ ṙ */
Marko Mikulicic 0:c0ecb8bf28eb 8765 0x1e5a, 501, /* Ṛ ṛ */
Marko Mikulicic 0:c0ecb8bf28eb 8766 0x1e5c, 501, /* Ṝ ṝ */
Marko Mikulicic 0:c0ecb8bf28eb 8767 0x1e5e, 501, /* Ṟ ṟ */
Marko Mikulicic 0:c0ecb8bf28eb 8768 0x1e60, 501, /* Ṡ ṡ */
Marko Mikulicic 0:c0ecb8bf28eb 8769 0x1e62, 501, /* Ṣ ṣ */
Marko Mikulicic 0:c0ecb8bf28eb 8770 0x1e64, 501, /* Ṥ ṥ */
Marko Mikulicic 0:c0ecb8bf28eb 8771 0x1e66, 501, /* Ṧ ṧ */
Marko Mikulicic 0:c0ecb8bf28eb 8772 0x1e68, 501, /* Ṩ ṩ */
Marko Mikulicic 0:c0ecb8bf28eb 8773 0x1e6a, 501, /* Ṫ ṫ */
Marko Mikulicic 0:c0ecb8bf28eb 8774 0x1e6c, 501, /* Ṭ ṭ */
Marko Mikulicic 0:c0ecb8bf28eb 8775 0x1e6e, 501, /* Ṯ ṯ */
Marko Mikulicic 0:c0ecb8bf28eb 8776 0x1e70, 501, /* Ṱ ṱ */
Marko Mikulicic 0:c0ecb8bf28eb 8777 0x1e72, 501, /* Ṳ ṳ */
Marko Mikulicic 0:c0ecb8bf28eb 8778 0x1e74, 501, /* Ṵ ṵ */
Marko Mikulicic 0:c0ecb8bf28eb 8779 0x1e76, 501, /* Ṷ ṷ */
Marko Mikulicic 0:c0ecb8bf28eb 8780 0x1e78, 501, /* Ṹ ṹ */
Marko Mikulicic 0:c0ecb8bf28eb 8781 0x1e7a, 501, /* Ṻ ṻ */
Marko Mikulicic 0:c0ecb8bf28eb 8782 0x1e7c, 501, /* Ṽ ṽ */
Marko Mikulicic 0:c0ecb8bf28eb 8783 0x1e7e, 501, /* Ṿ ṿ */
Marko Mikulicic 0:c0ecb8bf28eb 8784 0x1e80, 501, /* Ẁ ẁ */
Marko Mikulicic 0:c0ecb8bf28eb 8785 0x1e82, 501, /* Ẃ ẃ */
Marko Mikulicic 0:c0ecb8bf28eb 8786 0x1e84, 501, /* Ẅ ẅ */
Marko Mikulicic 0:c0ecb8bf28eb 8787 0x1e86, 501, /* Ẇ ẇ */
Marko Mikulicic 0:c0ecb8bf28eb 8788 0x1e88, 501, /* Ẉ ẉ */
Marko Mikulicic 0:c0ecb8bf28eb 8789 0x1e8a, 501, /* Ẋ ẋ */
Marko Mikulicic 0:c0ecb8bf28eb 8790 0x1e8c, 501, /* Ẍ ẍ */
Marko Mikulicic 0:c0ecb8bf28eb 8791 0x1e8e, 501, /* Ẏ ẏ */
Marko Mikulicic 0:c0ecb8bf28eb 8792 0x1e90, 501, /* Ẑ ẑ */
Marko Mikulicic 0:c0ecb8bf28eb 8793 0x1e92, 501, /* Ẓ ẓ */
Marko Mikulicic 0:c0ecb8bf28eb 8794 0x1e94, 501, /* Ẕ ẕ */
Marko Mikulicic 0:c0ecb8bf28eb 8795 0x1ea0, 501, /* Ạ ạ */
Marko Mikulicic 0:c0ecb8bf28eb 8796 0x1ea2, 501, /* Ả ả */
Marko Mikulicic 0:c0ecb8bf28eb 8797 0x1ea4, 501, /* Ấ ấ */
Marko Mikulicic 0:c0ecb8bf28eb 8798 0x1ea6, 501, /* Ầ ầ */
Marko Mikulicic 0:c0ecb8bf28eb 8799 0x1ea8, 501, /* Ẩ ẩ */
Marko Mikulicic 0:c0ecb8bf28eb 8800 0x1eaa, 501, /* Ẫ ẫ */
Marko Mikulicic 0:c0ecb8bf28eb 8801 0x1eac, 501, /* Ậ ậ */
Marko Mikulicic 0:c0ecb8bf28eb 8802 0x1eae, 501, /* Ắ ắ */
Marko Mikulicic 0:c0ecb8bf28eb 8803 0x1eb0, 501, /* Ằ ằ */
Marko Mikulicic 0:c0ecb8bf28eb 8804 0x1eb2, 501, /* Ẳ ẳ */
Marko Mikulicic 0:c0ecb8bf28eb 8805 0x1eb4, 501, /* Ẵ ẵ */
Marko Mikulicic 0:c0ecb8bf28eb 8806 0x1eb6, 501, /* Ặ ặ */
Marko Mikulicic 0:c0ecb8bf28eb 8807 0x1eb8, 501, /* Ẹ ẹ */
Marko Mikulicic 0:c0ecb8bf28eb 8808 0x1eba, 501, /* Ẻ ẻ */
Marko Mikulicic 0:c0ecb8bf28eb 8809 0x1ebc, 501, /* Ẽ ẽ */
Marko Mikulicic 0:c0ecb8bf28eb 8810 0x1ebe, 501, /* Ế ế */
Marko Mikulicic 0:c0ecb8bf28eb 8811 0x1ec0, 501, /* Ề ề */
Marko Mikulicic 0:c0ecb8bf28eb 8812 0x1ec2, 501, /* Ể ể */
Marko Mikulicic 0:c0ecb8bf28eb 8813 0x1ec4, 501, /* Ễ ễ */
Marko Mikulicic 0:c0ecb8bf28eb 8814 0x1ec6, 501, /* Ệ ệ */
Marko Mikulicic 0:c0ecb8bf28eb 8815 0x1ec8, 501, /* Ỉ ỉ */
Marko Mikulicic 0:c0ecb8bf28eb 8816 0x1eca, 501, /* Ị ị */
Marko Mikulicic 0:c0ecb8bf28eb 8817 0x1ecc, 501, /* Ọ ọ */
Marko Mikulicic 0:c0ecb8bf28eb 8818 0x1ece, 501, /* Ỏ ỏ */
Marko Mikulicic 0:c0ecb8bf28eb 8819 0x1ed0, 501, /* Ố ố */
Marko Mikulicic 0:c0ecb8bf28eb 8820 0x1ed2, 501, /* Ồ ồ */
Marko Mikulicic 0:c0ecb8bf28eb 8821 0x1ed4, 501, /* Ổ ổ */
Marko Mikulicic 0:c0ecb8bf28eb 8822 0x1ed6, 501, /* Ỗ ỗ */
Marko Mikulicic 0:c0ecb8bf28eb 8823 0x1ed8, 501, /* Ộ ộ */
Marko Mikulicic 0:c0ecb8bf28eb 8824 0x1eda, 501, /* Ớ ớ */
Marko Mikulicic 0:c0ecb8bf28eb 8825 0x1edc, 501, /* Ờ ờ */
Marko Mikulicic 0:c0ecb8bf28eb 8826 0x1ede, 501, /* Ở ở */
Marko Mikulicic 0:c0ecb8bf28eb 8827 0x1ee0, 501, /* Ỡ ỡ */
Marko Mikulicic 0:c0ecb8bf28eb 8828 0x1ee2, 501, /* Ợ ợ */
Marko Mikulicic 0:c0ecb8bf28eb 8829 0x1ee4, 501, /* Ụ ụ */
Marko Mikulicic 0:c0ecb8bf28eb 8830 0x1ee6, 501, /* Ủ ủ */
Marko Mikulicic 0:c0ecb8bf28eb 8831 0x1ee8, 501, /* Ứ ứ */
Marko Mikulicic 0:c0ecb8bf28eb 8832 0x1eea, 501, /* Ừ ừ */
Marko Mikulicic 0:c0ecb8bf28eb 8833 0x1eec, 501, /* Ử ử */
Marko Mikulicic 0:c0ecb8bf28eb 8834 0x1eee, 501, /* Ữ ữ */
Marko Mikulicic 0:c0ecb8bf28eb 8835 0x1ef0, 501, /* Ự ự */
Marko Mikulicic 0:c0ecb8bf28eb 8836 0x1ef2, 501, /* Ỳ ỳ */
Marko Mikulicic 0:c0ecb8bf28eb 8837 0x1ef4, 501, /* Ỵ ỵ */
Marko Mikulicic 0:c0ecb8bf28eb 8838 0x1ef6, 501, /* Ỷ ỷ */
Marko Mikulicic 0:c0ecb8bf28eb 8839 0x1ef8, 501, /* Ỹ ỹ */
Marko Mikulicic 0:c0ecb8bf28eb 8840 0x1f59, 492, /* Ὑ ὑ */
Marko Mikulicic 0:c0ecb8bf28eb 8841 0x1f5b, 492, /* Ὓ ὓ */
Marko Mikulicic 0:c0ecb8bf28eb 8842 0x1f5d, 492, /* Ὕ ὕ */
Marko Mikulicic 0:c0ecb8bf28eb 8843 0x1f5f, 492, /* Ὗ ὗ */
Marko Mikulicic 0:c0ecb8bf28eb 8844 0x1fbc, 491, /* ᾼ ᾳ */
Marko Mikulicic 0:c0ecb8bf28eb 8845 0x1fcc, 491, /* ῌ ῃ */
Marko Mikulicic 0:c0ecb8bf28eb 8846 0x1fec, 493, /* Ῥ ῥ */
Marko Mikulicic 0:c0ecb8bf28eb 8847 0x1ffc, 491, /* ῼ ῳ */
Marko Mikulicic 0:c0ecb8bf28eb 8848 };
Marko Mikulicic 0:c0ecb8bf28eb 8849
Marko Mikulicic 0:c0ecb8bf28eb 8850 static Rune *rune_bsearch(Rune c, Rune *t, int n, int ne) {
Marko Mikulicic 0:c0ecb8bf28eb 8851 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8852 int m;
Marko Mikulicic 0:c0ecb8bf28eb 8853
Marko Mikulicic 0:c0ecb8bf28eb 8854 while (n > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 8855 m = n / 2;
Marko Mikulicic 0:c0ecb8bf28eb 8856 p = t + m * ne;
Marko Mikulicic 0:c0ecb8bf28eb 8857 if (c >= p[0]) {
Marko Mikulicic 0:c0ecb8bf28eb 8858 t = p;
Marko Mikulicic 0:c0ecb8bf28eb 8859 n = n - m;
Marko Mikulicic 0:c0ecb8bf28eb 8860 } else
Marko Mikulicic 0:c0ecb8bf28eb 8861 n = m;
Marko Mikulicic 0:c0ecb8bf28eb 8862 }
Marko Mikulicic 0:c0ecb8bf28eb 8863 if (n && c >= t[0]) return t;
Marko Mikulicic 0:c0ecb8bf28eb 8864 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8865 }
Marko Mikulicic 0:c0ecb8bf28eb 8866
Marko Mikulicic 0:c0ecb8bf28eb 8867 Rune tolowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8868 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8869
Marko Mikulicic 0:c0ecb8bf28eb 8870 p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8871 if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8872 p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8873 if (p && c == p[0]) return c + p[1] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8874 return c;
Marko Mikulicic 0:c0ecb8bf28eb 8875 }
Marko Mikulicic 0:c0ecb8bf28eb 8876
Marko Mikulicic 0:c0ecb8bf28eb 8877 Rune toupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8878 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8879
Marko Mikulicic 0:c0ecb8bf28eb 8880 p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8881 if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8882 p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8883 if (p && c == p[0]) return c + p[1] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8884 return c;
Marko Mikulicic 0:c0ecb8bf28eb 8885 }
Marko Mikulicic 0:c0ecb8bf28eb 8886
Marko Mikulicic 0:c0ecb8bf28eb 8887 int islowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8888 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8889
Marko Mikulicic 0:c0ecb8bf28eb 8890 p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8891 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8892 p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8893 if (p && c == p[0]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8894 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8895 }
Marko Mikulicic 0:c0ecb8bf28eb 8896
Marko Mikulicic 0:c0ecb8bf28eb 8897 int isupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8898 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8899
Marko Mikulicic 0:c0ecb8bf28eb 8900 p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8901 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8902 p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8903 if (p && c == p[0]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8904 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8905 }
Marko Mikulicic 0:c0ecb8bf28eb 8906
Marko Mikulicic 0:c0ecb8bf28eb 8907 int isdigitrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8908 return c >= '0' && c <= '9';
Marko Mikulicic 0:c0ecb8bf28eb 8909 }
Marko Mikulicic 0:c0ecb8bf28eb 8910
Marko Mikulicic 0:c0ecb8bf28eb 8911 int isnewline(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8912 return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
Marko Mikulicic 0:c0ecb8bf28eb 8913 }
Marko Mikulicic 0:c0ecb8bf28eb 8914
Marko Mikulicic 0:c0ecb8bf28eb 8915 int iswordchar(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8916 return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') ||
Marko Mikulicic 0:c0ecb8bf28eb 8917 (c >= 'A' && c <= 'Z');
Marko Mikulicic 0:c0ecb8bf28eb 8918 }
Marko Mikulicic 0:c0ecb8bf28eb 8919
Marko Mikulicic 0:c0ecb8bf28eb 8920 int isalpharune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8921 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8922
Marko Mikulicic 0:c0ecb8bf28eb 8923 if (isupperrune(c) || islowerrune(c)) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8924 p = rune_bsearch(c, __alpha2, nelem(__alpha2) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8925 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8926 p = rune_bsearch(c, __alpha1, nelem(__alpha1), 1);
Marko Mikulicic 0:c0ecb8bf28eb 8927 if (p && c == p[0]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8928 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8929 }
Marko Mikulicic 0:c0ecb8bf28eb 8930
Marko Mikulicic 0:c0ecb8bf28eb 8931 int isspacerune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8932 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8933
Marko Mikulicic 0:c0ecb8bf28eb 8934 p = rune_bsearch(c, __space2, nelem(__space2) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8935 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8936 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8937 }
Marko Mikulicic 0:c0ecb8bf28eb 8938
Marko Mikulicic 0:c0ecb8bf28eb 8939 #else /* CS_ENABLE_UTF8 */
Marko Mikulicic 0:c0ecb8bf28eb 8940
Marko Mikulicic 0:c0ecb8bf28eb 8941 int chartorune(Rune *rune, const char *str) {
Marko Mikulicic 0:c0ecb8bf28eb 8942 *rune = *(uchar *) str;
Marko Mikulicic 0:c0ecb8bf28eb 8943 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8944 }
Marko Mikulicic 0:c0ecb8bf28eb 8945
Marko Mikulicic 0:c0ecb8bf28eb 8946 int fullrune(const char *str, int n) {
Marko Mikulicic 0:c0ecb8bf28eb 8947 (void) str;
Marko Mikulicic 0:c0ecb8bf28eb 8948 return (n <= 0) ? 0 : 1;
Marko Mikulicic 0:c0ecb8bf28eb 8949 }
Marko Mikulicic 0:c0ecb8bf28eb 8950
Marko Mikulicic 0:c0ecb8bf28eb 8951 int isdigitrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8952 return isdigit(c);
Marko Mikulicic 0:c0ecb8bf28eb 8953 }
Marko Mikulicic 0:c0ecb8bf28eb 8954
Marko Mikulicic 0:c0ecb8bf28eb 8955 int isnewline(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8956 return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
Marko Mikulicic 0:c0ecb8bf28eb 8957 }
Marko Mikulicic 0:c0ecb8bf28eb 8958
Marko Mikulicic 0:c0ecb8bf28eb 8959 int iswordchar(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8960 return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') ||
Marko Mikulicic 0:c0ecb8bf28eb 8961 (c >= 'A' && c <= 'Z');
Marko Mikulicic 0:c0ecb8bf28eb 8962 }
Marko Mikulicic 0:c0ecb8bf28eb 8963
Marko Mikulicic 0:c0ecb8bf28eb 8964 int isalpharune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8965 return isalpha(c);
Marko Mikulicic 0:c0ecb8bf28eb 8966 }
Marko Mikulicic 0:c0ecb8bf28eb 8967 int islowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8968 return islower(c);
Marko Mikulicic 0:c0ecb8bf28eb 8969 }
Marko Mikulicic 0:c0ecb8bf28eb 8970 int isspacerune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8971 return isspace(c);
Marko Mikulicic 0:c0ecb8bf28eb 8972 }
Marko Mikulicic 0:c0ecb8bf28eb 8973 int isupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8974 return isupper(c);
Marko Mikulicic 0:c0ecb8bf28eb 8975 }
Marko Mikulicic 0:c0ecb8bf28eb 8976
Marko Mikulicic 0:c0ecb8bf28eb 8977 int runetochar(char *str, Rune *rune) {
Marko Mikulicic 0:c0ecb8bf28eb 8978 str[0] = (char) *rune;
Marko Mikulicic 0:c0ecb8bf28eb 8979 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8980 }
Marko Mikulicic 0:c0ecb8bf28eb 8981
Marko Mikulicic 0:c0ecb8bf28eb 8982 Rune tolowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8983 return tolower(c);
Marko Mikulicic 0:c0ecb8bf28eb 8984 }
Marko Mikulicic 0:c0ecb8bf28eb 8985 Rune toupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8986 return toupper(c);
Marko Mikulicic 0:c0ecb8bf28eb 8987 }
Marko Mikulicic 0:c0ecb8bf28eb 8988 int utfnlen(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 8989 (void) s;
Marko Mikulicic 0:c0ecb8bf28eb 8990 return (int) c_strnlen(s, (size_t) m);
Marko Mikulicic 0:c0ecb8bf28eb 8991 }
Marko Mikulicic 0:c0ecb8bf28eb 8992
Marko Mikulicic 0:c0ecb8bf28eb 8993 const char *utfnshift(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 8994 return s + m;
Marko Mikulicic 0:c0ecb8bf28eb 8995 }
Marko Mikulicic 0:c0ecb8bf28eb 8996
Marko Mikulicic 0:c0ecb8bf28eb 8997 #endif /* CS_ENABLE_UTF8 */
Marko Mikulicic 0:c0ecb8bf28eb 8998
Marko Mikulicic 0:c0ecb8bf28eb 8999 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9000 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9001 #line 1 "common/base64.c"
Marko Mikulicic 0:c0ecb8bf28eb 9002 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9003 /*
Marko Mikulicic 0:c0ecb8bf28eb 9004 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 9005 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 9006 */
Marko Mikulicic 0:c0ecb8bf28eb 9007
Marko Mikulicic 0:c0ecb8bf28eb 9008 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 9009
Marko Mikulicic 0:c0ecb8bf28eb 9010 /* Amalgamated: #include "common/base64.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9011 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 9012
Marko Mikulicic 0:c0ecb8bf28eb 9013 /* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
Marko Mikulicic 0:c0ecb8bf28eb 9014
Marko Mikulicic 0:c0ecb8bf28eb 9015 #define NUM_UPPERCASES ('Z' - 'A' + 1)
Marko Mikulicic 0:c0ecb8bf28eb 9016 #define NUM_LETTERS (NUM_UPPERCASES * 2)
Marko Mikulicic 0:c0ecb8bf28eb 9017 #define NUM_DIGITS ('9' - '0' + 1)
Marko Mikulicic 0:c0ecb8bf28eb 9018
Marko Mikulicic 0:c0ecb8bf28eb 9019 /*
Marko Mikulicic 0:c0ecb8bf28eb 9020 * Emit a base64 code char.
Marko Mikulicic 0:c0ecb8bf28eb 9021 *
Marko Mikulicic 0:c0ecb8bf28eb 9022 * Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps
Marko Mikulicic 0:c0ecb8bf28eb 9023 */
Marko Mikulicic 0:c0ecb8bf28eb 9024 static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v) {
Marko Mikulicic 0:c0ecb8bf28eb 9025 if (v < NUM_UPPERCASES) {
Marko Mikulicic 0:c0ecb8bf28eb 9026 ctx->b64_putc(v + 'A', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 9027 } else if (v < (NUM_LETTERS)) {
Marko Mikulicic 0:c0ecb8bf28eb 9028 ctx->b64_putc(v - NUM_UPPERCASES + 'a', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 9029 } else if (v < (NUM_LETTERS + NUM_DIGITS)) {
Marko Mikulicic 0:c0ecb8bf28eb 9030 ctx->b64_putc(v - NUM_LETTERS + '0', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 9031 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9032 ctx->b64_putc(v - NUM_LETTERS - NUM_DIGITS == 0 ? '+' : '/',
Marko Mikulicic 0:c0ecb8bf28eb 9033 ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 9034 }
Marko Mikulicic 0:c0ecb8bf28eb 9035 }
Marko Mikulicic 0:c0ecb8bf28eb 9036
Marko Mikulicic 0:c0ecb8bf28eb 9037 static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9038 int a, b, c;
Marko Mikulicic 0:c0ecb8bf28eb 9039
Marko Mikulicic 0:c0ecb8bf28eb 9040 a = ctx->chunk[0];
Marko Mikulicic 0:c0ecb8bf28eb 9041 b = ctx->chunk[1];
Marko Mikulicic 0:c0ecb8bf28eb 9042 c = ctx->chunk[2];
Marko Mikulicic 0:c0ecb8bf28eb 9043
Marko Mikulicic 0:c0ecb8bf28eb 9044 cs_base64_emit_code(ctx, a >> 2);
Marko Mikulicic 0:c0ecb8bf28eb 9045 cs_base64_emit_code(ctx, ((a & 3) << 4) | (b >> 4));
Marko Mikulicic 0:c0ecb8bf28eb 9046 if (ctx->chunk_size > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 9047 cs_base64_emit_code(ctx, (b & 15) << 2 | (c >> 6));
Marko Mikulicic 0:c0ecb8bf28eb 9048 }
Marko Mikulicic 0:c0ecb8bf28eb 9049 if (ctx->chunk_size > 2) {
Marko Mikulicic 0:c0ecb8bf28eb 9050 cs_base64_emit_code(ctx, c & 63);
Marko Mikulicic 0:c0ecb8bf28eb 9051 }
Marko Mikulicic 0:c0ecb8bf28eb 9052 }
Marko Mikulicic 0:c0ecb8bf28eb 9053
Marko Mikulicic 0:c0ecb8bf28eb 9054 void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc,
Marko Mikulicic 0:c0ecb8bf28eb 9055 void *user_data) {
Marko Mikulicic 0:c0ecb8bf28eb 9056 ctx->chunk_size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9057 ctx->b64_putc = b64_putc;
Marko Mikulicic 0:c0ecb8bf28eb 9058 ctx->user_data = user_data;
Marko Mikulicic 0:c0ecb8bf28eb 9059 }
Marko Mikulicic 0:c0ecb8bf28eb 9060
Marko Mikulicic 0:c0ecb8bf28eb 9061 void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9062 const unsigned char *src = (const unsigned char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 9063 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 9064 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9065 ctx->chunk[ctx->chunk_size++] = src[i];
Marko Mikulicic 0:c0ecb8bf28eb 9066 if (ctx->chunk_size == 3) {
Marko Mikulicic 0:c0ecb8bf28eb 9067 cs_base64_emit_chunk(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9068 ctx->chunk_size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9069 }
Marko Mikulicic 0:c0ecb8bf28eb 9070 }
Marko Mikulicic 0:c0ecb8bf28eb 9071 }
Marko Mikulicic 0:c0ecb8bf28eb 9072
Marko Mikulicic 0:c0ecb8bf28eb 9073 void cs_base64_finish(struct cs_base64_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9074 if (ctx->chunk_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9075 int i;
Marko Mikulicic 0:c0ecb8bf28eb 9076 memset(&ctx->chunk[ctx->chunk_size], 0, 3 - ctx->chunk_size);
Marko Mikulicic 0:c0ecb8bf28eb 9077 cs_base64_emit_chunk(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9078 for (i = 0; i < (3 - ctx->chunk_size); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9079 ctx->b64_putc('=', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 9080 }
Marko Mikulicic 0:c0ecb8bf28eb 9081 }
Marko Mikulicic 0:c0ecb8bf28eb 9082 }
Marko Mikulicic 0:c0ecb8bf28eb 9083
Marko Mikulicic 0:c0ecb8bf28eb 9084 #define BASE64_ENCODE_BODY \
Marko Mikulicic 0:c0ecb8bf28eb 9085 static const char *b64 = \
Marko Mikulicic 0:c0ecb8bf28eb 9086 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
Marko Mikulicic 0:c0ecb8bf28eb 9087 int i, j, a, b, c; \
Marko Mikulicic 0:c0ecb8bf28eb 9088 \
Marko Mikulicic 0:c0ecb8bf28eb 9089 for (i = j = 0; i < src_len; i += 3) { \
Marko Mikulicic 0:c0ecb8bf28eb 9090 a = src[i]; \
Marko Mikulicic 0:c0ecb8bf28eb 9091 b = i + 1 >= src_len ? 0 : src[i + 1]; \
Marko Mikulicic 0:c0ecb8bf28eb 9092 c = i + 2 >= src_len ? 0 : src[i + 2]; \
Marko Mikulicic 0:c0ecb8bf28eb 9093 \
Marko Mikulicic 0:c0ecb8bf28eb 9094 BASE64_OUT(b64[a >> 2]); \
Marko Mikulicic 0:c0ecb8bf28eb 9095 BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \
Marko Mikulicic 0:c0ecb8bf28eb 9096 if (i + 1 < src_len) { \
Marko Mikulicic 0:c0ecb8bf28eb 9097 BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \
Marko Mikulicic 0:c0ecb8bf28eb 9098 } \
Marko Mikulicic 0:c0ecb8bf28eb 9099 if (i + 2 < src_len) { \
Marko Mikulicic 0:c0ecb8bf28eb 9100 BASE64_OUT(b64[c & 63]); \
Marko Mikulicic 0:c0ecb8bf28eb 9101 } \
Marko Mikulicic 0:c0ecb8bf28eb 9102 } \
Marko Mikulicic 0:c0ecb8bf28eb 9103 \
Marko Mikulicic 0:c0ecb8bf28eb 9104 while (j % 4 != 0) { \
Marko Mikulicic 0:c0ecb8bf28eb 9105 BASE64_OUT('='); \
Marko Mikulicic 0:c0ecb8bf28eb 9106 } \
Marko Mikulicic 0:c0ecb8bf28eb 9107 BASE64_FLUSH()
Marko Mikulicic 0:c0ecb8bf28eb 9108
Marko Mikulicic 0:c0ecb8bf28eb 9109 #define BASE64_OUT(ch) \
Marko Mikulicic 0:c0ecb8bf28eb 9110 do { \
Marko Mikulicic 0:c0ecb8bf28eb 9111 dst[j++] = (ch); \
Marko Mikulicic 0:c0ecb8bf28eb 9112 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 9113
Marko Mikulicic 0:c0ecb8bf28eb 9114 #define BASE64_FLUSH() \
Marko Mikulicic 0:c0ecb8bf28eb 9115 do { \
Marko Mikulicic 0:c0ecb8bf28eb 9116 dst[j++] = '\0'; \
Marko Mikulicic 0:c0ecb8bf28eb 9117 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 9118
Marko Mikulicic 0:c0ecb8bf28eb 9119 void cs_base64_encode(const unsigned char *src, int src_len, char *dst) {
Marko Mikulicic 0:c0ecb8bf28eb 9120 BASE64_ENCODE_BODY;
Marko Mikulicic 0:c0ecb8bf28eb 9121 }
Marko Mikulicic 0:c0ecb8bf28eb 9122
Marko Mikulicic 0:c0ecb8bf28eb 9123 #undef BASE64_OUT
Marko Mikulicic 0:c0ecb8bf28eb 9124 #undef BASE64_FLUSH
Marko Mikulicic 0:c0ecb8bf28eb 9125
Marko Mikulicic 0:c0ecb8bf28eb 9126 #ifndef CS_DISABLE_STDIO
Marko Mikulicic 0:c0ecb8bf28eb 9127 #define BASE64_OUT(ch) \
Marko Mikulicic 0:c0ecb8bf28eb 9128 do { \
Marko Mikulicic 0:c0ecb8bf28eb 9129 fprintf(f, "%c", (ch)); \
Marko Mikulicic 0:c0ecb8bf28eb 9130 j++; \
Marko Mikulicic 0:c0ecb8bf28eb 9131 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 9132
Marko Mikulicic 0:c0ecb8bf28eb 9133 #define BASE64_FLUSH()
Marko Mikulicic 0:c0ecb8bf28eb 9134
Marko Mikulicic 0:c0ecb8bf28eb 9135 void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len) {
Marko Mikulicic 0:c0ecb8bf28eb 9136 BASE64_ENCODE_BODY;
Marko Mikulicic 0:c0ecb8bf28eb 9137 }
Marko Mikulicic 0:c0ecb8bf28eb 9138
Marko Mikulicic 0:c0ecb8bf28eb 9139 #undef BASE64_OUT
Marko Mikulicic 0:c0ecb8bf28eb 9140 #undef BASE64_FLUSH
Marko Mikulicic 0:c0ecb8bf28eb 9141 #endif /* !CS_DISABLE_STDIO */
Marko Mikulicic 0:c0ecb8bf28eb 9142
Marko Mikulicic 0:c0ecb8bf28eb 9143 /* Convert one byte of encoded base64 input stream to 6-bit chunk */
Marko Mikulicic 0:c0ecb8bf28eb 9144 static unsigned char from_b64(unsigned char ch) {
Marko Mikulicic 0:c0ecb8bf28eb 9145 /* Inverse lookup map */
Marko Mikulicic 0:c0ecb8bf28eb 9146 static const unsigned char tab[128] = {
Marko Mikulicic 0:c0ecb8bf28eb 9147 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9148 255, 255, 255, 255, /* 0 */
Marko Mikulicic 0:c0ecb8bf28eb 9149 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9150 255, 255, 255, 255, /* 8 */
Marko Mikulicic 0:c0ecb8bf28eb 9151 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9152 255, 255, 255, 255, /* 16 */
Marko Mikulicic 0:c0ecb8bf28eb 9153 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9154 255, 255, 255, 255, /* 24 */
Marko Mikulicic 0:c0ecb8bf28eb 9155 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9156 255, 255, 255, 255, /* 32 */
Marko Mikulicic 0:c0ecb8bf28eb 9157 255, 255, 255, 62,
Marko Mikulicic 0:c0ecb8bf28eb 9158 255, 255, 255, 63, /* 40 */
Marko Mikulicic 0:c0ecb8bf28eb 9159 52, 53, 54, 55,
Marko Mikulicic 0:c0ecb8bf28eb 9160 56, 57, 58, 59, /* 48 */
Marko Mikulicic 0:c0ecb8bf28eb 9161 60, 61, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9162 255, 200, 255, 255, /* 56 '=' is 200, on index 61 */
Marko Mikulicic 0:c0ecb8bf28eb 9163 255, 0, 1, 2,
Marko Mikulicic 0:c0ecb8bf28eb 9164 3, 4, 5, 6, /* 64 */
Marko Mikulicic 0:c0ecb8bf28eb 9165 7, 8, 9, 10,
Marko Mikulicic 0:c0ecb8bf28eb 9166 11, 12, 13, 14, /* 72 */
Marko Mikulicic 0:c0ecb8bf28eb 9167 15, 16, 17, 18,
Marko Mikulicic 0:c0ecb8bf28eb 9168 19, 20, 21, 22, /* 80 */
Marko Mikulicic 0:c0ecb8bf28eb 9169 23, 24, 25, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9170 255, 255, 255, 255, /* 88 */
Marko Mikulicic 0:c0ecb8bf28eb 9171 255, 26, 27, 28,
Marko Mikulicic 0:c0ecb8bf28eb 9172 29, 30, 31, 32, /* 96 */
Marko Mikulicic 0:c0ecb8bf28eb 9173 33, 34, 35, 36,
Marko Mikulicic 0:c0ecb8bf28eb 9174 37, 38, 39, 40, /* 104 */
Marko Mikulicic 0:c0ecb8bf28eb 9175 41, 42, 43, 44,
Marko Mikulicic 0:c0ecb8bf28eb 9176 45, 46, 47, 48, /* 112 */
Marko Mikulicic 0:c0ecb8bf28eb 9177 49, 50, 51, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9178 255, 255, 255, 255, /* 120 */
Marko Mikulicic 0:c0ecb8bf28eb 9179 };
Marko Mikulicic 0:c0ecb8bf28eb 9180 return tab[ch & 127];
Marko Mikulicic 0:c0ecb8bf28eb 9181 }
Marko Mikulicic 0:c0ecb8bf28eb 9182
Marko Mikulicic 0:c0ecb8bf28eb 9183 int cs_base64_decode(const unsigned char *s, int len, char *dst) {
Marko Mikulicic 0:c0ecb8bf28eb 9184 unsigned char a, b, c, d;
Marko Mikulicic 0:c0ecb8bf28eb 9185 int orig_len = len;
Marko Mikulicic 0:c0ecb8bf28eb 9186 while (len >= 4 && (a = from_b64(s[0])) != 255 &&
Marko Mikulicic 0:c0ecb8bf28eb 9187 (b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 &&
Marko Mikulicic 0:c0ecb8bf28eb 9188 (d = from_b64(s[3])) != 255) {
Marko Mikulicic 0:c0ecb8bf28eb 9189 s += 4;
Marko Mikulicic 0:c0ecb8bf28eb 9190 len -= 4;
Marko Mikulicic 0:c0ecb8bf28eb 9191 if (a == 200 || b == 200) break; /* '=' can't be there */
Marko Mikulicic 0:c0ecb8bf28eb 9192 *dst++ = a << 2 | b >> 4;
Marko Mikulicic 0:c0ecb8bf28eb 9193 if (c == 200) break;
Marko Mikulicic 0:c0ecb8bf28eb 9194 *dst++ = b << 4 | c >> 2;
Marko Mikulicic 0:c0ecb8bf28eb 9195 if (d == 200) break;
Marko Mikulicic 0:c0ecb8bf28eb 9196 *dst++ = c << 6 | d;
Marko Mikulicic 0:c0ecb8bf28eb 9197 }
Marko Mikulicic 0:c0ecb8bf28eb 9198 *dst = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9199 return orig_len - len;
Marko Mikulicic 0:c0ecb8bf28eb 9200 }
Marko Mikulicic 0:c0ecb8bf28eb 9201
Marko Mikulicic 0:c0ecb8bf28eb 9202 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9203 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9204 #line 1 "common/md5.c"
Marko Mikulicic 0:c0ecb8bf28eb 9205 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9206 /*
Marko Mikulicic 0:c0ecb8bf28eb 9207 * This code implements the MD5 message-digest algorithm.
Marko Mikulicic 0:c0ecb8bf28eb 9208 * The algorithm is due to Ron Rivest. This code was
Marko Mikulicic 0:c0ecb8bf28eb 9209 * written by Colin Plumb in 1993, no copyright is claimed.
Marko Mikulicic 0:c0ecb8bf28eb 9210 * This code is in the public domain; do with it what you wish.
Marko Mikulicic 0:c0ecb8bf28eb 9211 *
Marko Mikulicic 0:c0ecb8bf28eb 9212 * Equivalent code is available from RSA Data Security, Inc.
Marko Mikulicic 0:c0ecb8bf28eb 9213 * This code has been tested against that, and is equivalent,
Marko Mikulicic 0:c0ecb8bf28eb 9214 * except that you don't need to include two pages of legalese
Marko Mikulicic 0:c0ecb8bf28eb 9215 * with every copy.
Marko Mikulicic 0:c0ecb8bf28eb 9216 *
Marko Mikulicic 0:c0ecb8bf28eb 9217 * To compute the message digest of a chunk of bytes, declare an
Marko Mikulicic 0:c0ecb8bf28eb 9218 * MD5Context structure, pass it to MD5Init, call MD5Update as
Marko Mikulicic 0:c0ecb8bf28eb 9219 * needed on buffers full of bytes, and then call MD5Final, which
Marko Mikulicic 0:c0ecb8bf28eb 9220 * will fill a supplied 16-byte array with the digest.
Marko Mikulicic 0:c0ecb8bf28eb 9221 */
Marko Mikulicic 0:c0ecb8bf28eb 9222
Marko Mikulicic 0:c0ecb8bf28eb 9223 #if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON)
Marko Mikulicic 0:c0ecb8bf28eb 9224
Marko Mikulicic 0:c0ecb8bf28eb 9225 /* Amalgamated: #include "common/md5.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9226
Marko Mikulicic 0:c0ecb8bf28eb 9227 #ifndef CS_ENABLE_NATIVE_MD5
Marko Mikulicic 0:c0ecb8bf28eb 9228 static void byteReverse(unsigned char *buf, unsigned longs) {
Marko Mikulicic 0:c0ecb8bf28eb 9229 /* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
Marko Mikulicic 0:c0ecb8bf28eb 9230 #if BYTE_ORDER == BIG_ENDIAN
Marko Mikulicic 0:c0ecb8bf28eb 9231 do {
Marko Mikulicic 0:c0ecb8bf28eb 9232 uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 |
Marko Mikulicic 0:c0ecb8bf28eb 9233 ((unsigned) buf[1] << 8 | buf[0]);
Marko Mikulicic 0:c0ecb8bf28eb 9234 *(uint32_t *) buf = t;
Marko Mikulicic 0:c0ecb8bf28eb 9235 buf += 4;
Marko Mikulicic 0:c0ecb8bf28eb 9236 } while (--longs);
Marko Mikulicic 0:c0ecb8bf28eb 9237 #else
Marko Mikulicic 0:c0ecb8bf28eb 9238 (void) buf;
Marko Mikulicic 0:c0ecb8bf28eb 9239 (void) longs;
Marko Mikulicic 0:c0ecb8bf28eb 9240 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9241 }
Marko Mikulicic 0:c0ecb8bf28eb 9242
Marko Mikulicic 0:c0ecb8bf28eb 9243 #define F1(x, y, z) (z ^ (x & (y ^ z)))
Marko Mikulicic 0:c0ecb8bf28eb 9244 #define F2(x, y, z) F1(z, x, y)
Marko Mikulicic 0:c0ecb8bf28eb 9245 #define F3(x, y, z) (x ^ y ^ z)
Marko Mikulicic 0:c0ecb8bf28eb 9246 #define F4(x, y, z) (y ^ (x | ~z))
Marko Mikulicic 0:c0ecb8bf28eb 9247
Marko Mikulicic 0:c0ecb8bf28eb 9248 #define MD5STEP(f, w, x, y, z, data, s) \
Marko Mikulicic 0:c0ecb8bf28eb 9249 (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
Marko Mikulicic 0:c0ecb8bf28eb 9250
Marko Mikulicic 0:c0ecb8bf28eb 9251 /*
Marko Mikulicic 0:c0ecb8bf28eb 9252 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
Marko Mikulicic 0:c0ecb8bf28eb 9253 * initialization constants.
Marko Mikulicic 0:c0ecb8bf28eb 9254 */
Marko Mikulicic 0:c0ecb8bf28eb 9255 void MD5_Init(MD5_CTX *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9256 ctx->buf[0] = 0x67452301;
Marko Mikulicic 0:c0ecb8bf28eb 9257 ctx->buf[1] = 0xefcdab89;
Marko Mikulicic 0:c0ecb8bf28eb 9258 ctx->buf[2] = 0x98badcfe;
Marko Mikulicic 0:c0ecb8bf28eb 9259 ctx->buf[3] = 0x10325476;
Marko Mikulicic 0:c0ecb8bf28eb 9260
Marko Mikulicic 0:c0ecb8bf28eb 9261 ctx->bits[0] = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9262 ctx->bits[1] = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9263 }
Marko Mikulicic 0:c0ecb8bf28eb 9264
Marko Mikulicic 0:c0ecb8bf28eb 9265 static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
Marko Mikulicic 0:c0ecb8bf28eb 9266 register uint32_t a, b, c, d;
Marko Mikulicic 0:c0ecb8bf28eb 9267
Marko Mikulicic 0:c0ecb8bf28eb 9268 a = buf[0];
Marko Mikulicic 0:c0ecb8bf28eb 9269 b = buf[1];
Marko Mikulicic 0:c0ecb8bf28eb 9270 c = buf[2];
Marko Mikulicic 0:c0ecb8bf28eb 9271 d = buf[3];
Marko Mikulicic 0:c0ecb8bf28eb 9272
Marko Mikulicic 0:c0ecb8bf28eb 9273 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9274 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9275 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9276 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9277 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9278 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9279 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9280 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9281 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9282 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9283 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9284 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9285 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9286 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9287 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9288 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9289
Marko Mikulicic 0:c0ecb8bf28eb 9290 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9291 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9292 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9293 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9294 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9295 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9296 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9297 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9298 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9299 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9300 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9301 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9302 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9303 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9304 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9305 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9306
Marko Mikulicic 0:c0ecb8bf28eb 9307 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9308 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9309 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9310 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9311 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9312 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9313 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9314 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9315 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9316 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9317 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9318 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9319 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9320 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9321 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9322 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9323
Marko Mikulicic 0:c0ecb8bf28eb 9324 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9325 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9326 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9327 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9328 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9329 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9330 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9331 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9332 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9333 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9334 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9335 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9336 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9337 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9338 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9339 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9340
Marko Mikulicic 0:c0ecb8bf28eb 9341 buf[0] += a;
Marko Mikulicic 0:c0ecb8bf28eb 9342 buf[1] += b;
Marko Mikulicic 0:c0ecb8bf28eb 9343 buf[2] += c;
Marko Mikulicic 0:c0ecb8bf28eb 9344 buf[3] += d;
Marko Mikulicic 0:c0ecb8bf28eb 9345 }
Marko Mikulicic 0:c0ecb8bf28eb 9346
Marko Mikulicic 0:c0ecb8bf28eb 9347 void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9348 uint32_t t;
Marko Mikulicic 0:c0ecb8bf28eb 9349
Marko Mikulicic 0:c0ecb8bf28eb 9350 t = ctx->bits[0];
Marko Mikulicic 0:c0ecb8bf28eb 9351 if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++;
Marko Mikulicic 0:c0ecb8bf28eb 9352 ctx->bits[1] += (uint32_t) len >> 29;
Marko Mikulicic 0:c0ecb8bf28eb 9353
Marko Mikulicic 0:c0ecb8bf28eb 9354 t = (t >> 3) & 0x3f;
Marko Mikulicic 0:c0ecb8bf28eb 9355
Marko Mikulicic 0:c0ecb8bf28eb 9356 if (t) {
Marko Mikulicic 0:c0ecb8bf28eb 9357 unsigned char *p = (unsigned char *) ctx->in + t;
Marko Mikulicic 0:c0ecb8bf28eb 9358
Marko Mikulicic 0:c0ecb8bf28eb 9359 t = 64 - t;
Marko Mikulicic 0:c0ecb8bf28eb 9360 if (len < t) {
Marko Mikulicic 0:c0ecb8bf28eb 9361 memcpy(p, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 9362 return;
Marko Mikulicic 0:c0ecb8bf28eb 9363 }
Marko Mikulicic 0:c0ecb8bf28eb 9364 memcpy(p, buf, t);
Marko Mikulicic 0:c0ecb8bf28eb 9365 byteReverse(ctx->in, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9366 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9367 buf += t;
Marko Mikulicic 0:c0ecb8bf28eb 9368 len -= t;
Marko Mikulicic 0:c0ecb8bf28eb 9369 }
Marko Mikulicic 0:c0ecb8bf28eb 9370
Marko Mikulicic 0:c0ecb8bf28eb 9371 while (len >= 64) {
Marko Mikulicic 0:c0ecb8bf28eb 9372 memcpy(ctx->in, buf, 64);
Marko Mikulicic 0:c0ecb8bf28eb 9373 byteReverse(ctx->in, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9374 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9375 buf += 64;
Marko Mikulicic 0:c0ecb8bf28eb 9376 len -= 64;
Marko Mikulicic 0:c0ecb8bf28eb 9377 }
Marko Mikulicic 0:c0ecb8bf28eb 9378
Marko Mikulicic 0:c0ecb8bf28eb 9379 memcpy(ctx->in, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 9380 }
Marko Mikulicic 0:c0ecb8bf28eb 9381
Marko Mikulicic 0:c0ecb8bf28eb 9382 void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9383 unsigned count;
Marko Mikulicic 0:c0ecb8bf28eb 9384 unsigned char *p;
Marko Mikulicic 0:c0ecb8bf28eb 9385 uint32_t *a;
Marko Mikulicic 0:c0ecb8bf28eb 9386
Marko Mikulicic 0:c0ecb8bf28eb 9387 count = (ctx->bits[0] >> 3) & 0x3F;
Marko Mikulicic 0:c0ecb8bf28eb 9388
Marko Mikulicic 0:c0ecb8bf28eb 9389 p = ctx->in + count;
Marko Mikulicic 0:c0ecb8bf28eb 9390 *p++ = 0x80;
Marko Mikulicic 0:c0ecb8bf28eb 9391 count = 64 - 1 - count;
Marko Mikulicic 0:c0ecb8bf28eb 9392 if (count < 8) {
Marko Mikulicic 0:c0ecb8bf28eb 9393 memset(p, 0, count);
Marko Mikulicic 0:c0ecb8bf28eb 9394 byteReverse(ctx->in, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9395 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9396 memset(ctx->in, 0, 56);
Marko Mikulicic 0:c0ecb8bf28eb 9397 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9398 memset(p, 0, count - 8);
Marko Mikulicic 0:c0ecb8bf28eb 9399 }
Marko Mikulicic 0:c0ecb8bf28eb 9400 byteReverse(ctx->in, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9401
Marko Mikulicic 0:c0ecb8bf28eb 9402 a = (uint32_t *) ctx->in;
Marko Mikulicic 0:c0ecb8bf28eb 9403 a[14] = ctx->bits[0];
Marko Mikulicic 0:c0ecb8bf28eb 9404 a[15] = ctx->bits[1];
Marko Mikulicic 0:c0ecb8bf28eb 9405
Marko Mikulicic 0:c0ecb8bf28eb 9406 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9407 byteReverse((unsigned char *) ctx->buf, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9408 memcpy(digest, ctx->buf, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9409 memset((char *) ctx, 0, sizeof(*ctx));
Marko Mikulicic 0:c0ecb8bf28eb 9410 }
Marko Mikulicic 0:c0ecb8bf28eb 9411 #endif /* CS_ENABLE_NATIVE_MD5 */
Marko Mikulicic 0:c0ecb8bf28eb 9412
Marko Mikulicic 0:c0ecb8bf28eb 9413 /*
Marko Mikulicic 0:c0ecb8bf28eb 9414 * Stringify binary data. Output buffer size must be 2 * size_of_input + 1
Marko Mikulicic 0:c0ecb8bf28eb 9415 * because each byte of input takes 2 bytes in string representation
Marko Mikulicic 0:c0ecb8bf28eb 9416 * plus 1 byte for the terminating \0 character.
Marko Mikulicic 0:c0ecb8bf28eb 9417 */
Marko Mikulicic 0:c0ecb8bf28eb 9418 void cs_to_hex(char *to, const unsigned char *p, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9419 static const char *hex = "0123456789abcdef";
Marko Mikulicic 0:c0ecb8bf28eb 9420
Marko Mikulicic 0:c0ecb8bf28eb 9421 for (; len--; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 9422 *to++ = hex[p[0] >> 4];
Marko Mikulicic 0:c0ecb8bf28eb 9423 *to++ = hex[p[0] & 0x0f];
Marko Mikulicic 0:c0ecb8bf28eb 9424 }
Marko Mikulicic 0:c0ecb8bf28eb 9425 *to = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 9426 }
Marko Mikulicic 0:c0ecb8bf28eb 9427
Marko Mikulicic 0:c0ecb8bf28eb 9428 char *cs_md5(char buf[33], ...) {
Marko Mikulicic 0:c0ecb8bf28eb 9429 unsigned char hash[16];
Marko Mikulicic 0:c0ecb8bf28eb 9430 const unsigned char *p;
Marko Mikulicic 0:c0ecb8bf28eb 9431 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 9432 MD5_CTX ctx;
Marko Mikulicic 0:c0ecb8bf28eb 9433
Marko Mikulicic 0:c0ecb8bf28eb 9434 MD5_Init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9435
Marko Mikulicic 0:c0ecb8bf28eb 9436 va_start(ap, buf);
Marko Mikulicic 0:c0ecb8bf28eb 9437 while ((p = va_arg(ap, const unsigned char *) ) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9438 size_t len = va_arg(ap, size_t);
Marko Mikulicic 0:c0ecb8bf28eb 9439 MD5_Update(&ctx, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 9440 }
Marko Mikulicic 0:c0ecb8bf28eb 9441 va_end(ap);
Marko Mikulicic 0:c0ecb8bf28eb 9442
Marko Mikulicic 0:c0ecb8bf28eb 9443 MD5_Final(hash, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9444 cs_to_hex(buf, hash, sizeof(hash));
Marko Mikulicic 0:c0ecb8bf28eb 9445
Marko Mikulicic 0:c0ecb8bf28eb 9446 return buf;
Marko Mikulicic 0:c0ecb8bf28eb 9447 }
Marko Mikulicic 0:c0ecb8bf28eb 9448
Marko Mikulicic 0:c0ecb8bf28eb 9449 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9450 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9451 #line 1 "common/sha1.c"
Marko Mikulicic 0:c0ecb8bf28eb 9452 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9453 /* Copyright(c) By Steve Reid <steve@edmweb.com> */
Marko Mikulicic 0:c0ecb8bf28eb 9454 /* 100% Public Domain */
Marko Mikulicic 0:c0ecb8bf28eb 9455
Marko Mikulicic 0:c0ecb8bf28eb 9456 #if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
Marko Mikulicic 0:c0ecb8bf28eb 9457
Marko Mikulicic 0:c0ecb8bf28eb 9458 /* Amalgamated: #include "common/sha1.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9459
Marko Mikulicic 0:c0ecb8bf28eb 9460 #define SHA1HANDSOFF
Marko Mikulicic 0:c0ecb8bf28eb 9461 #if defined(__sun)
Marko Mikulicic 0:c0ecb8bf28eb 9462 /* Amalgamated: #include "common/solarisfixes.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9463 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9464
Marko Mikulicic 0:c0ecb8bf28eb 9465 union char64long16 {
Marko Mikulicic 0:c0ecb8bf28eb 9466 unsigned char c[64];
Marko Mikulicic 0:c0ecb8bf28eb 9467 uint32_t l[16];
Marko Mikulicic 0:c0ecb8bf28eb 9468 };
Marko Mikulicic 0:c0ecb8bf28eb 9469
Marko Mikulicic 0:c0ecb8bf28eb 9470 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
Marko Mikulicic 0:c0ecb8bf28eb 9471
Marko Mikulicic 0:c0ecb8bf28eb 9472 static uint32_t blk0(union char64long16 *block, int i) {
Marko Mikulicic 0:c0ecb8bf28eb 9473 /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
Marko Mikulicic 0:c0ecb8bf28eb 9474 #if BYTE_ORDER == LITTLE_ENDIAN
Marko Mikulicic 0:c0ecb8bf28eb 9475 block->l[i] =
Marko Mikulicic 0:c0ecb8bf28eb 9476 (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF);
Marko Mikulicic 0:c0ecb8bf28eb 9477 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9478 return block->l[i];
Marko Mikulicic 0:c0ecb8bf28eb 9479 }
Marko Mikulicic 0:c0ecb8bf28eb 9480
Marko Mikulicic 0:c0ecb8bf28eb 9481 /* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
Marko Mikulicic 0:c0ecb8bf28eb 9482 #undef blk
Marko Mikulicic 0:c0ecb8bf28eb 9483 #undef R0
Marko Mikulicic 0:c0ecb8bf28eb 9484 #undef R1
Marko Mikulicic 0:c0ecb8bf28eb 9485 #undef R2
Marko Mikulicic 0:c0ecb8bf28eb 9486 #undef R3
Marko Mikulicic 0:c0ecb8bf28eb 9487 #undef R4
Marko Mikulicic 0:c0ecb8bf28eb 9488
Marko Mikulicic 0:c0ecb8bf28eb 9489 #define blk(i) \
Marko Mikulicic 0:c0ecb8bf28eb 9490 (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
Marko Mikulicic 0:c0ecb8bf28eb 9491 block->l[(i + 2) & 15] ^ block->l[i & 15], \
Marko Mikulicic 0:c0ecb8bf28eb 9492 1))
Marko Mikulicic 0:c0ecb8bf28eb 9493 #define R0(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9494 z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9495 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9496 #define R1(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9497 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9498 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9499 #define R2(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9500 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9501 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9502 #define R3(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9503 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9504 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9505 #define R4(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9506 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9507 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9508
Marko Mikulicic 0:c0ecb8bf28eb 9509 void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) {
Marko Mikulicic 0:c0ecb8bf28eb 9510 uint32_t a, b, c, d, e;
Marko Mikulicic 0:c0ecb8bf28eb 9511 union char64long16 block[1];
Marko Mikulicic 0:c0ecb8bf28eb 9512
Marko Mikulicic 0:c0ecb8bf28eb 9513 memcpy(block, buffer, 64);
Marko Mikulicic 0:c0ecb8bf28eb 9514 a = state[0];
Marko Mikulicic 0:c0ecb8bf28eb 9515 b = state[1];
Marko Mikulicic 0:c0ecb8bf28eb 9516 c = state[2];
Marko Mikulicic 0:c0ecb8bf28eb 9517 d = state[3];
Marko Mikulicic 0:c0ecb8bf28eb 9518 e = state[4];
Marko Mikulicic 0:c0ecb8bf28eb 9519 R0(a, b, c, d, e, 0);
Marko Mikulicic 0:c0ecb8bf28eb 9520 R0(e, a, b, c, d, 1);
Marko Mikulicic 0:c0ecb8bf28eb 9521 R0(d, e, a, b, c, 2);
Marko Mikulicic 0:c0ecb8bf28eb 9522 R0(c, d, e, a, b, 3);
Marko Mikulicic 0:c0ecb8bf28eb 9523 R0(b, c, d, e, a, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9524 R0(a, b, c, d, e, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9525 R0(e, a, b, c, d, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9526 R0(d, e, a, b, c, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9527 R0(c, d, e, a, b, 8);
Marko Mikulicic 0:c0ecb8bf28eb 9528 R0(b, c, d, e, a, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9529 R0(a, b, c, d, e, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9530 R0(e, a, b, c, d, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9531 R0(d, e, a, b, c, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9532 R0(c, d, e, a, b, 13);
Marko Mikulicic 0:c0ecb8bf28eb 9533 R0(b, c, d, e, a, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9534 R0(a, b, c, d, e, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9535 R1(e, a, b, c, d, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9536 R1(d, e, a, b, c, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9537 R1(c, d, e, a, b, 18);
Marko Mikulicic 0:c0ecb8bf28eb 9538 R1(b, c, d, e, a, 19);
Marko Mikulicic 0:c0ecb8bf28eb 9539 R2(a, b, c, d, e, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9540 R2(e, a, b, c, d, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9541 R2(d, e, a, b, c, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9542 R2(c, d, e, a, b, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9543 R2(b, c, d, e, a, 24);
Marko Mikulicic 0:c0ecb8bf28eb 9544 R2(a, b, c, d, e, 25);
Marko Mikulicic 0:c0ecb8bf28eb 9545 R2(e, a, b, c, d, 26);
Marko Mikulicic 0:c0ecb8bf28eb 9546 R2(d, e, a, b, c, 27);
Marko Mikulicic 0:c0ecb8bf28eb 9547 R2(c, d, e, a, b, 28);
Marko Mikulicic 0:c0ecb8bf28eb 9548 R2(b, c, d, e, a, 29);
Marko Mikulicic 0:c0ecb8bf28eb 9549 R2(a, b, c, d, e, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9550 R2(e, a, b, c, d, 31);
Marko Mikulicic 0:c0ecb8bf28eb 9551 R2(d, e, a, b, c, 32);
Marko Mikulicic 0:c0ecb8bf28eb 9552 R2(c, d, e, a, b, 33);
Marko Mikulicic 0:c0ecb8bf28eb 9553 R2(b, c, d, e, a, 34);
Marko Mikulicic 0:c0ecb8bf28eb 9554 R2(a, b, c, d, e, 35);
Marko Mikulicic 0:c0ecb8bf28eb 9555 R2(e, a, b, c, d, 36);
Marko Mikulicic 0:c0ecb8bf28eb 9556 R2(d, e, a, b, c, 37);
Marko Mikulicic 0:c0ecb8bf28eb 9557 R2(c, d, e, a, b, 38);
Marko Mikulicic 0:c0ecb8bf28eb 9558 R2(b, c, d, e, a, 39);
Marko Mikulicic 0:c0ecb8bf28eb 9559 R3(a, b, c, d, e, 40);
Marko Mikulicic 0:c0ecb8bf28eb 9560 R3(e, a, b, c, d, 41);
Marko Mikulicic 0:c0ecb8bf28eb 9561 R3(d, e, a, b, c, 42);
Marko Mikulicic 0:c0ecb8bf28eb 9562 R3(c, d, e, a, b, 43);
Marko Mikulicic 0:c0ecb8bf28eb 9563 R3(b, c, d, e, a, 44);
Marko Mikulicic 0:c0ecb8bf28eb 9564 R3(a, b, c, d, e, 45);
Marko Mikulicic 0:c0ecb8bf28eb 9565 R3(e, a, b, c, d, 46);
Marko Mikulicic 0:c0ecb8bf28eb 9566 R3(d, e, a, b, c, 47);
Marko Mikulicic 0:c0ecb8bf28eb 9567 R3(c, d, e, a, b, 48);
Marko Mikulicic 0:c0ecb8bf28eb 9568 R3(b, c, d, e, a, 49);
Marko Mikulicic 0:c0ecb8bf28eb 9569 R3(a, b, c, d, e, 50);
Marko Mikulicic 0:c0ecb8bf28eb 9570 R3(e, a, b, c, d, 51);
Marko Mikulicic 0:c0ecb8bf28eb 9571 R3(d, e, a, b, c, 52);
Marko Mikulicic 0:c0ecb8bf28eb 9572 R3(c, d, e, a, b, 53);
Marko Mikulicic 0:c0ecb8bf28eb 9573 R3(b, c, d, e, a, 54);
Marko Mikulicic 0:c0ecb8bf28eb 9574 R3(a, b, c, d, e, 55);
Marko Mikulicic 0:c0ecb8bf28eb 9575 R3(e, a, b, c, d, 56);
Marko Mikulicic 0:c0ecb8bf28eb 9576 R3(d, e, a, b, c, 57);
Marko Mikulicic 0:c0ecb8bf28eb 9577 R3(c, d, e, a, b, 58);
Marko Mikulicic 0:c0ecb8bf28eb 9578 R3(b, c, d, e, a, 59);
Marko Mikulicic 0:c0ecb8bf28eb 9579 R4(a, b, c, d, e, 60);
Marko Mikulicic 0:c0ecb8bf28eb 9580 R4(e, a, b, c, d, 61);
Marko Mikulicic 0:c0ecb8bf28eb 9581 R4(d, e, a, b, c, 62);
Marko Mikulicic 0:c0ecb8bf28eb 9582 R4(c, d, e, a, b, 63);
Marko Mikulicic 0:c0ecb8bf28eb 9583 R4(b, c, d, e, a, 64);
Marko Mikulicic 0:c0ecb8bf28eb 9584 R4(a, b, c, d, e, 65);
Marko Mikulicic 0:c0ecb8bf28eb 9585 R4(e, a, b, c, d, 66);
Marko Mikulicic 0:c0ecb8bf28eb 9586 R4(d, e, a, b, c, 67);
Marko Mikulicic 0:c0ecb8bf28eb 9587 R4(c, d, e, a, b, 68);
Marko Mikulicic 0:c0ecb8bf28eb 9588 R4(b, c, d, e, a, 69);
Marko Mikulicic 0:c0ecb8bf28eb 9589 R4(a, b, c, d, e, 70);
Marko Mikulicic 0:c0ecb8bf28eb 9590 R4(e, a, b, c, d, 71);
Marko Mikulicic 0:c0ecb8bf28eb 9591 R4(d, e, a, b, c, 72);
Marko Mikulicic 0:c0ecb8bf28eb 9592 R4(c, d, e, a, b, 73);
Marko Mikulicic 0:c0ecb8bf28eb 9593 R4(b, c, d, e, a, 74);
Marko Mikulicic 0:c0ecb8bf28eb 9594 R4(a, b, c, d, e, 75);
Marko Mikulicic 0:c0ecb8bf28eb 9595 R4(e, a, b, c, d, 76);
Marko Mikulicic 0:c0ecb8bf28eb 9596 R4(d, e, a, b, c, 77);
Marko Mikulicic 0:c0ecb8bf28eb 9597 R4(c, d, e, a, b, 78);
Marko Mikulicic 0:c0ecb8bf28eb 9598 R4(b, c, d, e, a, 79);
Marko Mikulicic 0:c0ecb8bf28eb 9599 state[0] += a;
Marko Mikulicic 0:c0ecb8bf28eb 9600 state[1] += b;
Marko Mikulicic 0:c0ecb8bf28eb 9601 state[2] += c;
Marko Mikulicic 0:c0ecb8bf28eb 9602 state[3] += d;
Marko Mikulicic 0:c0ecb8bf28eb 9603 state[4] += e;
Marko Mikulicic 0:c0ecb8bf28eb 9604 /* Erase working structures. The order of operations is important,
Marko Mikulicic 0:c0ecb8bf28eb 9605 * used to ensure that compiler doesn't optimize those out. */
Marko Mikulicic 0:c0ecb8bf28eb 9606 memset(block, 0, sizeof(block));
Marko Mikulicic 0:c0ecb8bf28eb 9607 a = b = c = d = e = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9608 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 9609 (void) b;
Marko Mikulicic 0:c0ecb8bf28eb 9610 (void) c;
Marko Mikulicic 0:c0ecb8bf28eb 9611 (void) d;
Marko Mikulicic 0:c0ecb8bf28eb 9612 (void) e;
Marko Mikulicic 0:c0ecb8bf28eb 9613 }
Marko Mikulicic 0:c0ecb8bf28eb 9614
Marko Mikulicic 0:c0ecb8bf28eb 9615 void cs_sha1_init(cs_sha1_ctx *context) {
Marko Mikulicic 0:c0ecb8bf28eb 9616 context->state[0] = 0x67452301;
Marko Mikulicic 0:c0ecb8bf28eb 9617 context->state[1] = 0xEFCDAB89;
Marko Mikulicic 0:c0ecb8bf28eb 9618 context->state[2] = 0x98BADCFE;
Marko Mikulicic 0:c0ecb8bf28eb 9619 context->state[3] = 0x10325476;
Marko Mikulicic 0:c0ecb8bf28eb 9620 context->state[4] = 0xC3D2E1F0;
Marko Mikulicic 0:c0ecb8bf28eb 9621 context->count[0] = context->count[1] = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9622 }
Marko Mikulicic 0:c0ecb8bf28eb 9623
Marko Mikulicic 0:c0ecb8bf28eb 9624 void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data,
Marko Mikulicic 0:c0ecb8bf28eb 9625 uint32_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9626 uint32_t i, j;
Marko Mikulicic 0:c0ecb8bf28eb 9627
Marko Mikulicic 0:c0ecb8bf28eb 9628 j = context->count[0];
Marko Mikulicic 0:c0ecb8bf28eb 9629 if ((context->count[0] += len << 3) < j) context->count[1]++;
Marko Mikulicic 0:c0ecb8bf28eb 9630 context->count[1] += (len >> 29);
Marko Mikulicic 0:c0ecb8bf28eb 9631 j = (j >> 3) & 63;
Marko Mikulicic 0:c0ecb8bf28eb 9632 if ((j + len) > 63) {
Marko Mikulicic 0:c0ecb8bf28eb 9633 memcpy(&context->buffer[j], data, (i = 64 - j));
Marko Mikulicic 0:c0ecb8bf28eb 9634 cs_sha1_transform(context->state, context->buffer);
Marko Mikulicic 0:c0ecb8bf28eb 9635 for (; i + 63 < len; i += 64) {
Marko Mikulicic 0:c0ecb8bf28eb 9636 cs_sha1_transform(context->state, &data[i]);
Marko Mikulicic 0:c0ecb8bf28eb 9637 }
Marko Mikulicic 0:c0ecb8bf28eb 9638 j = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9639 } else
Marko Mikulicic 0:c0ecb8bf28eb 9640 i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9641 memcpy(&context->buffer[j], &data[i], len - i);
Marko Mikulicic 0:c0ecb8bf28eb 9642 }
Marko Mikulicic 0:c0ecb8bf28eb 9643
Marko Mikulicic 0:c0ecb8bf28eb 9644 void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context) {
Marko Mikulicic 0:c0ecb8bf28eb 9645 unsigned i;
Marko Mikulicic 0:c0ecb8bf28eb 9646 unsigned char finalcount[8], c;
Marko Mikulicic 0:c0ecb8bf28eb 9647
Marko Mikulicic 0:c0ecb8bf28eb 9648 for (i = 0; i < 8; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9649 finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >>
Marko Mikulicic 0:c0ecb8bf28eb 9650 ((3 - (i & 3)) * 8)) &
Marko Mikulicic 0:c0ecb8bf28eb 9651 255);
Marko Mikulicic 0:c0ecb8bf28eb 9652 }
Marko Mikulicic 0:c0ecb8bf28eb 9653 c = 0200;
Marko Mikulicic 0:c0ecb8bf28eb 9654 cs_sha1_update(context, &c, 1);
Marko Mikulicic 0:c0ecb8bf28eb 9655 while ((context->count[0] & 504) != 448) {
Marko Mikulicic 0:c0ecb8bf28eb 9656 c = 0000;
Marko Mikulicic 0:c0ecb8bf28eb 9657 cs_sha1_update(context, &c, 1);
Marko Mikulicic 0:c0ecb8bf28eb 9658 }
Marko Mikulicic 0:c0ecb8bf28eb 9659 cs_sha1_update(context, finalcount, 8);
Marko Mikulicic 0:c0ecb8bf28eb 9660 for (i = 0; i < 20; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9661 digest[i] =
Marko Mikulicic 0:c0ecb8bf28eb 9662 (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
Marko Mikulicic 0:c0ecb8bf28eb 9663 }
Marko Mikulicic 0:c0ecb8bf28eb 9664 memset(context, '\0', sizeof(*context));
Marko Mikulicic 0:c0ecb8bf28eb 9665 memset(&finalcount, '\0', sizeof(finalcount));
Marko Mikulicic 0:c0ecb8bf28eb 9666 }
Marko Mikulicic 0:c0ecb8bf28eb 9667
Marko Mikulicic 0:c0ecb8bf28eb 9668 void cs_hmac_sha1(const unsigned char *key, size_t keylen,
Marko Mikulicic 0:c0ecb8bf28eb 9669 const unsigned char *data, size_t datalen,
Marko Mikulicic 0:c0ecb8bf28eb 9670 unsigned char out[20]) {
Marko Mikulicic 0:c0ecb8bf28eb 9671 cs_sha1_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 9672 unsigned char buf1[64], buf2[64], tmp_key[20], i;
Marko Mikulicic 0:c0ecb8bf28eb 9673
Marko Mikulicic 0:c0ecb8bf28eb 9674 if (keylen > sizeof(buf1)) {
Marko Mikulicic 0:c0ecb8bf28eb 9675 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9676 cs_sha1_update(&ctx, key, keylen);
Marko Mikulicic 0:c0ecb8bf28eb 9677 cs_sha1_final(tmp_key, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9678 key = tmp_key;
Marko Mikulicic 0:c0ecb8bf28eb 9679 keylen = sizeof(tmp_key);
Marko Mikulicic 0:c0ecb8bf28eb 9680 }
Marko Mikulicic 0:c0ecb8bf28eb 9681
Marko Mikulicic 0:c0ecb8bf28eb 9682 memset(buf1, 0, sizeof(buf1));
Marko Mikulicic 0:c0ecb8bf28eb 9683 memset(buf2, 0, sizeof(buf2));
Marko Mikulicic 0:c0ecb8bf28eb 9684 memcpy(buf1, key, keylen);
Marko Mikulicic 0:c0ecb8bf28eb 9685 memcpy(buf2, key, keylen);
Marko Mikulicic 0:c0ecb8bf28eb 9686
Marko Mikulicic 0:c0ecb8bf28eb 9687 for (i = 0; i < sizeof(buf1); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9688 buf1[i] ^= 0x36;
Marko Mikulicic 0:c0ecb8bf28eb 9689 buf2[i] ^= 0x5c;
Marko Mikulicic 0:c0ecb8bf28eb 9690 }
Marko Mikulicic 0:c0ecb8bf28eb 9691
Marko Mikulicic 0:c0ecb8bf28eb 9692 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9693 cs_sha1_update(&ctx, buf1, sizeof(buf1));
Marko Mikulicic 0:c0ecb8bf28eb 9694 cs_sha1_update(&ctx, data, datalen);
Marko Mikulicic 0:c0ecb8bf28eb 9695 cs_sha1_final(out, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9696
Marko Mikulicic 0:c0ecb8bf28eb 9697 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9698 cs_sha1_update(&ctx, buf2, sizeof(buf2));
Marko Mikulicic 0:c0ecb8bf28eb 9699 cs_sha1_update(&ctx, out, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9700 cs_sha1_final(out, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9701 }
Marko Mikulicic 0:c0ecb8bf28eb 9702
Marko Mikulicic 0:c0ecb8bf28eb 9703 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9704 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9705 #line 1 "common/cs_dirent.c"
Marko Mikulicic 0:c0ecb8bf28eb 9706 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9707 /*
Marko Mikulicic 0:c0ecb8bf28eb 9708 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 9709 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 9710 */
Marko Mikulicic 0:c0ecb8bf28eb 9711
Marko Mikulicic 0:c0ecb8bf28eb 9712 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 9713
Marko Mikulicic 0:c0ecb8bf28eb 9714 /* Amalgamated: #include "common/cs_dirent.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9715
Marko Mikulicic 0:c0ecb8bf28eb 9716 /*
Marko Mikulicic 0:c0ecb8bf28eb 9717 * This file contains POSIX opendir/closedir/readdir API implementation
Marko Mikulicic 0:c0ecb8bf28eb 9718 * for systems which do not natively support it (e.g. Windows).
Marko Mikulicic 0:c0ecb8bf28eb 9719 */
Marko Mikulicic 0:c0ecb8bf28eb 9720
Marko Mikulicic 0:c0ecb8bf28eb 9721 #ifndef MG_FREE
Marko Mikulicic 0:c0ecb8bf28eb 9722 #define MG_FREE free
Marko Mikulicic 0:c0ecb8bf28eb 9723 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9724
Marko Mikulicic 0:c0ecb8bf28eb 9725 #ifndef MG_MALLOC
Marko Mikulicic 0:c0ecb8bf28eb 9726 #define MG_MALLOC malloc
Marko Mikulicic 0:c0ecb8bf28eb 9727 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9728
Marko Mikulicic 0:c0ecb8bf28eb 9729 #ifdef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 9730 DIR *opendir(const char *name) {
Marko Mikulicic 0:c0ecb8bf28eb 9731 DIR *dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9732 wchar_t wpath[MAX_PATH];
Marko Mikulicic 0:c0ecb8bf28eb 9733 DWORD attrs;
Marko Mikulicic 0:c0ecb8bf28eb 9734
Marko Mikulicic 0:c0ecb8bf28eb 9735 if (name == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9736 SetLastError(ERROR_BAD_ARGUMENTS);
Marko Mikulicic 0:c0ecb8bf28eb 9737 } else if ((dir = (DIR *) MG_MALLOC(sizeof(*dir))) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9738 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Marko Mikulicic 0:c0ecb8bf28eb 9739 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9740 to_wchar(name, wpath, ARRAY_SIZE(wpath));
Marko Mikulicic 0:c0ecb8bf28eb 9741 attrs = GetFileAttributesW(wpath);
Marko Mikulicic 0:c0ecb8bf28eb 9742 if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
Marko Mikulicic 0:c0ecb8bf28eb 9743 (void) wcscat(wpath, L"\\*");
Marko Mikulicic 0:c0ecb8bf28eb 9744 dir->handle = FindFirstFileW(wpath, &dir->info);
Marko Mikulicic 0:c0ecb8bf28eb 9745 dir->result.d_name[0] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 9746 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9747 MG_FREE(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9748 dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9749 }
Marko Mikulicic 0:c0ecb8bf28eb 9750 }
Marko Mikulicic 0:c0ecb8bf28eb 9751
Marko Mikulicic 0:c0ecb8bf28eb 9752 return dir;
Marko Mikulicic 0:c0ecb8bf28eb 9753 }
Marko Mikulicic 0:c0ecb8bf28eb 9754
Marko Mikulicic 0:c0ecb8bf28eb 9755 int closedir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9756 int result = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9757
Marko Mikulicic 0:c0ecb8bf28eb 9758 if (dir != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9759 if (dir->handle != INVALID_HANDLE_VALUE)
Marko Mikulicic 0:c0ecb8bf28eb 9760 result = FindClose(dir->handle) ? 0 : -1;
Marko Mikulicic 0:c0ecb8bf28eb 9761 MG_FREE(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9762 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9763 result = -1;
Marko Mikulicic 0:c0ecb8bf28eb 9764 SetLastError(ERROR_BAD_ARGUMENTS);
Marko Mikulicic 0:c0ecb8bf28eb 9765 }
Marko Mikulicic 0:c0ecb8bf28eb 9766
Marko Mikulicic 0:c0ecb8bf28eb 9767 return result;
Marko Mikulicic 0:c0ecb8bf28eb 9768 }
Marko Mikulicic 0:c0ecb8bf28eb 9769
Marko Mikulicic 0:c0ecb8bf28eb 9770 struct dirent *readdir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9771 struct dirent *result = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9772
Marko Mikulicic 0:c0ecb8bf28eb 9773 if (dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9774 if (dir->handle != INVALID_HANDLE_VALUE) {
Marko Mikulicic 0:c0ecb8bf28eb 9775 result = &dir->result;
Marko Mikulicic 0:c0ecb8bf28eb 9776 (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1,
Marko Mikulicic 0:c0ecb8bf28eb 9777 result->d_name, sizeof(result->d_name), NULL,
Marko Mikulicic 0:c0ecb8bf28eb 9778 NULL);
Marko Mikulicic 0:c0ecb8bf28eb 9779
Marko Mikulicic 0:c0ecb8bf28eb 9780 if (!FindNextFileW(dir->handle, &dir->info)) {
Marko Mikulicic 0:c0ecb8bf28eb 9781 (void) FindClose(dir->handle);
Marko Mikulicic 0:c0ecb8bf28eb 9782 dir->handle = INVALID_HANDLE_VALUE;
Marko Mikulicic 0:c0ecb8bf28eb 9783 }
Marko Mikulicic 0:c0ecb8bf28eb 9784
Marko Mikulicic 0:c0ecb8bf28eb 9785 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9786 SetLastError(ERROR_FILE_NOT_FOUND);
Marko Mikulicic 0:c0ecb8bf28eb 9787 }
Marko Mikulicic 0:c0ecb8bf28eb 9788 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9789 SetLastError(ERROR_BAD_ARGUMENTS);
Marko Mikulicic 0:c0ecb8bf28eb 9790 }
Marko Mikulicic 0:c0ecb8bf28eb 9791
Marko Mikulicic 0:c0ecb8bf28eb 9792 return result;
Marko Mikulicic 0:c0ecb8bf28eb 9793 }
Marko Mikulicic 0:c0ecb8bf28eb 9794 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9795
Marko Mikulicic 0:c0ecb8bf28eb 9796 #ifdef CS_ENABLE_SPIFFS
Marko Mikulicic 0:c0ecb8bf28eb 9797
Marko Mikulicic 0:c0ecb8bf28eb 9798 DIR *opendir(const char *dir_name) {
Marko Mikulicic 0:c0ecb8bf28eb 9799 DIR *dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9800 extern spiffs fs;
Marko Mikulicic 0:c0ecb8bf28eb 9801
Marko Mikulicic 0:c0ecb8bf28eb 9802 if (dir_name != NULL && (dir = (DIR *) malloc(sizeof(*dir))) != NULL &&
Marko Mikulicic 0:c0ecb8bf28eb 9803 SPIFFS_opendir(&fs, (char *) dir_name, &dir->dh) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9804 free(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9805 dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9806 }
Marko Mikulicic 0:c0ecb8bf28eb 9807
Marko Mikulicic 0:c0ecb8bf28eb 9808 return dir;
Marko Mikulicic 0:c0ecb8bf28eb 9809 }
Marko Mikulicic 0:c0ecb8bf28eb 9810
Marko Mikulicic 0:c0ecb8bf28eb 9811 int closedir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9812 if (dir != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9813 SPIFFS_closedir(&dir->dh);
Marko Mikulicic 0:c0ecb8bf28eb 9814 free(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9815 }
Marko Mikulicic 0:c0ecb8bf28eb 9816 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 9817 }
Marko Mikulicic 0:c0ecb8bf28eb 9818
Marko Mikulicic 0:c0ecb8bf28eb 9819 struct dirent *readdir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9820 return SPIFFS_readdir(&dir->dh, &dir->de);
Marko Mikulicic 0:c0ecb8bf28eb 9821 }
Marko Mikulicic 0:c0ecb8bf28eb 9822
Marko Mikulicic 0:c0ecb8bf28eb 9823 /* SPIFFs doesn't support directory operations */
Marko Mikulicic 0:c0ecb8bf28eb 9824 int rmdir(const char *path) {
Marko Mikulicic 0:c0ecb8bf28eb 9825 (void) path;
Marko Mikulicic 0:c0ecb8bf28eb 9826 return ENOTDIR;
Marko Mikulicic 0:c0ecb8bf28eb 9827 }
Marko Mikulicic 0:c0ecb8bf28eb 9828
Marko Mikulicic 0:c0ecb8bf28eb 9829 int mkdir(const char *path, mode_t mode) {
Marko Mikulicic 0:c0ecb8bf28eb 9830 (void) path;
Marko Mikulicic 0:c0ecb8bf28eb 9831 (void) mode;
Marko Mikulicic 0:c0ecb8bf28eb 9832 /* for spiffs supports only root dir, which comes from mongoose as '.' */
Marko Mikulicic 0:c0ecb8bf28eb 9833 return (strlen(path) == 1 && *path == '.') ? 0 : ENOTDIR;
Marko Mikulicic 0:c0ecb8bf28eb 9834 }
Marko Mikulicic 0:c0ecb8bf28eb 9835
Marko Mikulicic 0:c0ecb8bf28eb 9836 #endif /* CS_ENABLE_SPIFFS */
Marko Mikulicic 0:c0ecb8bf28eb 9837
Marko Mikulicic 0:c0ecb8bf28eb 9838 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9839
Marko Mikulicic 0:c0ecb8bf28eb 9840 /* ISO C requires a translation unit to contain at least one declaration */
Marko Mikulicic 0:c0ecb8bf28eb 9841 typedef int cs_dirent_dummy;
Marko Mikulicic 0:c0ecb8bf28eb 9842 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9843 #line 1 "common/cs_file.c"
Marko Mikulicic 0:c0ecb8bf28eb 9844 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9845 /*
Marko Mikulicic 0:c0ecb8bf28eb 9846 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 9847 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 9848 */
Marko Mikulicic 0:c0ecb8bf28eb 9849
Marko Mikulicic 0:c0ecb8bf28eb 9850 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9851
Marko Mikulicic 0:c0ecb8bf28eb 9852 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 9853 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 9854
Marko Mikulicic 0:c0ecb8bf28eb 9855 #ifdef CS_MMAP
Marko Mikulicic 0:c0ecb8bf28eb 9856 #include <fcntl.h>
Marko Mikulicic 0:c0ecb8bf28eb 9857 #include <sys/mman.h>
Marko Mikulicic 0:c0ecb8bf28eb 9858 #include <sys/stat.h>
Marko Mikulicic 0:c0ecb8bf28eb 9859 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9860
Marko Mikulicic 0:c0ecb8bf28eb 9861 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 9862 char *cs_read_file(const char *path, size_t *size) {
Marko Mikulicic 0:c0ecb8bf28eb 9863 FILE *fp;
Marko Mikulicic 0:c0ecb8bf28eb 9864 char *data = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9865 if ((fp = fopen(path, "rb")) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9866 } else if (fseek(fp, 0, SEEK_END) != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9867 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 9868 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9869 *size = ftell(fp);
Marko Mikulicic 0:c0ecb8bf28eb 9870 data = (char *) malloc(*size + 1);
Marko Mikulicic 0:c0ecb8bf28eb 9871 if (data != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9872 fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */
Marko Mikulicic 0:c0ecb8bf28eb 9873 if (fread(data, 1, *size, fp) != *size) {
Marko Mikulicic 0:c0ecb8bf28eb 9874 free(data);
Marko Mikulicic 0:c0ecb8bf28eb 9875 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9876 }
Marko Mikulicic 0:c0ecb8bf28eb 9877 data[*size] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 9878 }
Marko Mikulicic 0:c0ecb8bf28eb 9879 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 9880 }
Marko Mikulicic 0:c0ecb8bf28eb 9881 return data;
Marko Mikulicic 0:c0ecb8bf28eb 9882 }
Marko Mikulicic 0:c0ecb8bf28eb 9883 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9884
Marko Mikulicic 0:c0ecb8bf28eb 9885 #ifdef CS_MMAP
Marko Mikulicic 0:c0ecb8bf28eb 9886 char *cs_mmap_file(const char *path, size_t *size) {
Marko Mikulicic 0:c0ecb8bf28eb 9887 char *r;
Marko Mikulicic 0:c0ecb8bf28eb 9888 int fd = open(path, O_RDONLY);
Marko Mikulicic 0:c0ecb8bf28eb 9889 struct stat st;
Marko Mikulicic 0:c0ecb8bf28eb 9890 if (fd == -1) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9891 fstat(fd, &st);
Marko Mikulicic 0:c0ecb8bf28eb 9892 *size = (size_t) st.st_size;
Marko Mikulicic 0:c0ecb8bf28eb 9893 r = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Marko Mikulicic 0:c0ecb8bf28eb 9894 if (r == MAP_FAILED) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9895 return r;
Marko Mikulicic 0:c0ecb8bf28eb 9896 }
Marko Mikulicic 0:c0ecb8bf28eb 9897 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9898 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9899 #line 1 "common/cs_strtod.c"
Marko Mikulicic 0:c0ecb8bf28eb 9900 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9901 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 9902 #include <math.h>
Marko Mikulicic 0:c0ecb8bf28eb 9903
Marko Mikulicic 0:c0ecb8bf28eb 9904 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 9905
Marko Mikulicic 0:c0ecb8bf28eb 9906 int cs_strncasecmp(const char *s1, const char *s2, size_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 9907 if (n == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9908 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 9909 }
Marko Mikulicic 0:c0ecb8bf28eb 9910
Marko Mikulicic 0:c0ecb8bf28eb 9911 while (n-- != 0 && tolower((int) *s1) == tolower((int) *s2)) {
Marko Mikulicic 0:c0ecb8bf28eb 9912 if (n == 0 || *s1 == '\0' || *s2 == '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 9913 break;
Marko Mikulicic 0:c0ecb8bf28eb 9914 }
Marko Mikulicic 0:c0ecb8bf28eb 9915 s1++;
Marko Mikulicic 0:c0ecb8bf28eb 9916 s2++;
Marko Mikulicic 0:c0ecb8bf28eb 9917 }
Marko Mikulicic 0:c0ecb8bf28eb 9918
Marko Mikulicic 0:c0ecb8bf28eb 9919 return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
Marko Mikulicic 0:c0ecb8bf28eb 9920 }
Marko Mikulicic 0:c0ecb8bf28eb 9921
Marko Mikulicic 0:c0ecb8bf28eb 9922 /*
Marko Mikulicic 0:c0ecb8bf28eb 9923 * based on Source:
Marko Mikulicic 0:c0ecb8bf28eb 9924 * https://github.com/anakod/Sming/blob/master/Sming/system/stringconversion.cpp#L93
Marko Mikulicic 0:c0ecb8bf28eb 9925 */
Marko Mikulicic 0:c0ecb8bf28eb 9926
Marko Mikulicic 0:c0ecb8bf28eb 9927 double cs_strtod(const char *str, char **endptr) {
Marko Mikulicic 0:c0ecb8bf28eb 9928 double result = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 9929 char c;
Marko Mikulicic 0:c0ecb8bf28eb 9930 const char *str_start;
Marko Mikulicic 0:c0ecb8bf28eb 9931 struct {
Marko Mikulicic 0:c0ecb8bf28eb 9932 unsigned neg : 1; /* result is negative */
Marko Mikulicic 0:c0ecb8bf28eb 9933 unsigned decimals : 1; /* parsing decimal part */
Marko Mikulicic 0:c0ecb8bf28eb 9934 unsigned is_exp : 1; /* parsing exponent like e+5 */
Marko Mikulicic 0:c0ecb8bf28eb 9935 unsigned is_exp_neg : 1; /* exponent is negative */
Marko Mikulicic 0:c0ecb8bf28eb 9936 } flags = {0, 0, 0, 0};
Marko Mikulicic 0:c0ecb8bf28eb 9937
Marko Mikulicic 0:c0ecb8bf28eb 9938 while (isspace((int) *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 9939 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9940 }
Marko Mikulicic 0:c0ecb8bf28eb 9941
Marko Mikulicic 0:c0ecb8bf28eb 9942 if (*str == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9943 /* only space in str? */
Marko Mikulicic 0:c0ecb8bf28eb 9944 if (endptr != 0) *endptr = (char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 9945 return result;
Marko Mikulicic 0:c0ecb8bf28eb 9946 }
Marko Mikulicic 0:c0ecb8bf28eb 9947
Marko Mikulicic 0:c0ecb8bf28eb 9948 /* Handle leading plus/minus signs */
Marko Mikulicic 0:c0ecb8bf28eb 9949 while (*str == '-' || *str == '+') {
Marko Mikulicic 0:c0ecb8bf28eb 9950 if (*str == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 9951 flags.neg = !flags.neg;
Marko Mikulicic 0:c0ecb8bf28eb 9952 }
Marko Mikulicic 0:c0ecb8bf28eb 9953 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9954 }
Marko Mikulicic 0:c0ecb8bf28eb 9955
Marko Mikulicic 0:c0ecb8bf28eb 9956 if (cs_strncasecmp(str, "NaN", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9957 if (endptr != 0) *endptr = (char *) str + 3;
Marko Mikulicic 0:c0ecb8bf28eb 9958 return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 9959 }
Marko Mikulicic 0:c0ecb8bf28eb 9960
Marko Mikulicic 0:c0ecb8bf28eb 9961 if (cs_strncasecmp(str, "INF", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9962 str += 3;
Marko Mikulicic 0:c0ecb8bf28eb 9963 if (cs_strncasecmp(str, "INITY", 5) == 0) str += 5;
Marko Mikulicic 0:c0ecb8bf28eb 9964 if (endptr != 0) *endptr = (char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 9965 return flags.neg ? -INFINITY : INFINITY;
Marko Mikulicic 0:c0ecb8bf28eb 9966 }
Marko Mikulicic 0:c0ecb8bf28eb 9967
Marko Mikulicic 0:c0ecb8bf28eb 9968 str_start = str;
Marko Mikulicic 0:c0ecb8bf28eb 9969
Marko Mikulicic 0:c0ecb8bf28eb 9970 if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) {
Marko Mikulicic 0:c0ecb8bf28eb 9971 /* base 16 */
Marko Mikulicic 0:c0ecb8bf28eb 9972 str += 2;
Marko Mikulicic 0:c0ecb8bf28eb 9973 while ((c = tolower((int) *str))) {
Marko Mikulicic 0:c0ecb8bf28eb 9974 int d;
Marko Mikulicic 0:c0ecb8bf28eb 9975 if (c >= '0' && c <= '9') {
Marko Mikulicic 0:c0ecb8bf28eb 9976 d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 9977 } else if (c >= 'a' && c <= 'f') {
Marko Mikulicic 0:c0ecb8bf28eb 9978 d = 10 + (c - 'a');
Marko Mikulicic 0:c0ecb8bf28eb 9979 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9980 break;
Marko Mikulicic 0:c0ecb8bf28eb 9981 }
Marko Mikulicic 0:c0ecb8bf28eb 9982 result = 16 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 9983 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9984 }
Marko Mikulicic 0:c0ecb8bf28eb 9985 } else if (*str == '0' && (*(str + 1) == 'b' || *(str + 1) == 'B')) {
Marko Mikulicic 0:c0ecb8bf28eb 9986 /* base 2 */
Marko Mikulicic 0:c0ecb8bf28eb 9987 str += 2;
Marko Mikulicic 0:c0ecb8bf28eb 9988 while ((c = *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 9989 int d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 9990 if (c != '0' && c != '1') break;
Marko Mikulicic 0:c0ecb8bf28eb 9991 result = 2 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 9992 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9993 }
Marko Mikulicic 0:c0ecb8bf28eb 9994 } else if (*str == '0' && *(str + 1) >= '0' && *(str + 1) <= '7') {
Marko Mikulicic 0:c0ecb8bf28eb 9995 /* base 8 */
Marko Mikulicic 0:c0ecb8bf28eb 9996 while ((c = *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 9997 int d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 9998 if (c < '0' || c > '7') {
Marko Mikulicic 0:c0ecb8bf28eb 9999 /* fallback to base 10 */
Marko Mikulicic 0:c0ecb8bf28eb 10000 str = str_start;
Marko Mikulicic 0:c0ecb8bf28eb 10001 break;
Marko Mikulicic 0:c0ecb8bf28eb 10002 }
Marko Mikulicic 0:c0ecb8bf28eb 10003 result = 8 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 10004 str++;
Marko Mikulicic 0:c0ecb8bf28eb 10005 }
Marko Mikulicic 0:c0ecb8bf28eb 10006 }
Marko Mikulicic 0:c0ecb8bf28eb 10007
Marko Mikulicic 0:c0ecb8bf28eb 10008 if (str == str_start) {
Marko Mikulicic 0:c0ecb8bf28eb 10009 /* base 10 */
Marko Mikulicic 0:c0ecb8bf28eb 10010
Marko Mikulicic 0:c0ecb8bf28eb 10011 /* exponent specified explicitly, like in 3e-5, exponent is -5 */
Marko Mikulicic 0:c0ecb8bf28eb 10012 int exp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10013 /* exponent calculated from dot, like in 1.23, exponent is -2 */
Marko Mikulicic 0:c0ecb8bf28eb 10014 int exp_dot = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10015
Marko Mikulicic 0:c0ecb8bf28eb 10016 result = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10017
Marko Mikulicic 0:c0ecb8bf28eb 10018 while ((c = *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 10019 int d;
Marko Mikulicic 0:c0ecb8bf28eb 10020
Marko Mikulicic 0:c0ecb8bf28eb 10021 if (c == '.') {
Marko Mikulicic 0:c0ecb8bf28eb 10022 if (!flags.decimals) {
Marko Mikulicic 0:c0ecb8bf28eb 10023 /* going to parse decimal part */
Marko Mikulicic 0:c0ecb8bf28eb 10024 flags.decimals = 1;
Marko Mikulicic 0:c0ecb8bf28eb 10025 str++;
Marko Mikulicic 0:c0ecb8bf28eb 10026 continue;
Marko Mikulicic 0:c0ecb8bf28eb 10027 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10028 /* non-expected dot: assume number data is over */
Marko Mikulicic 0:c0ecb8bf28eb 10029 break;
Marko Mikulicic 0:c0ecb8bf28eb 10030 }
Marko Mikulicic 0:c0ecb8bf28eb 10031 } else if (c == 'e' || c == 'E') {
Marko Mikulicic 0:c0ecb8bf28eb 10032 /* going to parse exponent part */
Marko Mikulicic 0:c0ecb8bf28eb 10033 flags.is_exp = 1;
Marko Mikulicic 0:c0ecb8bf28eb 10034 str++;
Marko Mikulicic 0:c0ecb8bf28eb 10035 c = *str;
Marko Mikulicic 0:c0ecb8bf28eb 10036
Marko Mikulicic 0:c0ecb8bf28eb 10037 /* check sign of the exponent */
Marko Mikulicic 0:c0ecb8bf28eb 10038 if (c == '-' || c == '+') {
Marko Mikulicic 0:c0ecb8bf28eb 10039 if (c == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 10040 flags.is_exp_neg = 1;
Marko Mikulicic 0:c0ecb8bf28eb 10041 }
Marko Mikulicic 0:c0ecb8bf28eb 10042 str++;
Marko Mikulicic 0:c0ecb8bf28eb 10043 }
Marko Mikulicic 0:c0ecb8bf28eb 10044
Marko Mikulicic 0:c0ecb8bf28eb 10045 continue;
Marko Mikulicic 0:c0ecb8bf28eb 10046 }
Marko Mikulicic 0:c0ecb8bf28eb 10047
Marko Mikulicic 0:c0ecb8bf28eb 10048 d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 10049 if (d < 0 || d > 9) {
Marko Mikulicic 0:c0ecb8bf28eb 10050 break;
Marko Mikulicic 0:c0ecb8bf28eb 10051 }
Marko Mikulicic 0:c0ecb8bf28eb 10052
Marko Mikulicic 0:c0ecb8bf28eb 10053 if (!flags.is_exp) {
Marko Mikulicic 0:c0ecb8bf28eb 10054 /* apply current digit to the result */
Marko Mikulicic 0:c0ecb8bf28eb 10055 result = 10 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 10056 if (flags.decimals) {
Marko Mikulicic 0:c0ecb8bf28eb 10057 exp_dot--;
Marko Mikulicic 0:c0ecb8bf28eb 10058 }
Marko Mikulicic 0:c0ecb8bf28eb 10059 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10060 /* apply current digit to the exponent */
Marko Mikulicic 0:c0ecb8bf28eb 10061 if (flags.is_exp_neg) {
Marko Mikulicic 0:c0ecb8bf28eb 10062 if (exp > -1022) {
Marko Mikulicic 0:c0ecb8bf28eb 10063 exp = 10 * exp - d;
Marko Mikulicic 0:c0ecb8bf28eb 10064 }
Marko Mikulicic 0:c0ecb8bf28eb 10065 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10066 if (exp < 1023) {
Marko Mikulicic 0:c0ecb8bf28eb 10067 exp = 10 * exp + d;
Marko Mikulicic 0:c0ecb8bf28eb 10068 }
Marko Mikulicic 0:c0ecb8bf28eb 10069 }
Marko Mikulicic 0:c0ecb8bf28eb 10070 }
Marko Mikulicic 0:c0ecb8bf28eb 10071
Marko Mikulicic 0:c0ecb8bf28eb 10072 str++;
Marko Mikulicic 0:c0ecb8bf28eb 10073 }
Marko Mikulicic 0:c0ecb8bf28eb 10074
Marko Mikulicic 0:c0ecb8bf28eb 10075 exp += exp_dot;
Marko Mikulicic 0:c0ecb8bf28eb 10076
Marko Mikulicic 0:c0ecb8bf28eb 10077 /*
Marko Mikulicic 0:c0ecb8bf28eb 10078 * TODO(dfrank): it probably makes sense not to adjust intermediate `double
Marko Mikulicic 0:c0ecb8bf28eb 10079 * result`, but build double number accordingly to IEEE 754 from taken
Marko Mikulicic 0:c0ecb8bf28eb 10080 * (integer) mantissa, exponent and sign. That would work faster, and we
Marko Mikulicic 0:c0ecb8bf28eb 10081 * can avoid any possible round errors.
Marko Mikulicic 0:c0ecb8bf28eb 10082 */
Marko Mikulicic 0:c0ecb8bf28eb 10083
Marko Mikulicic 0:c0ecb8bf28eb 10084 /* if exponent is non-zero, apply it */
Marko Mikulicic 0:c0ecb8bf28eb 10085 if (exp != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10086 if (exp < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10087 while (exp++ != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10088 result /= 10;
Marko Mikulicic 0:c0ecb8bf28eb 10089 }
Marko Mikulicic 0:c0ecb8bf28eb 10090 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10091 while (exp-- != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10092 result *= 10;
Marko Mikulicic 0:c0ecb8bf28eb 10093 }
Marko Mikulicic 0:c0ecb8bf28eb 10094 }
Marko Mikulicic 0:c0ecb8bf28eb 10095 }
Marko Mikulicic 0:c0ecb8bf28eb 10096 }
Marko Mikulicic 0:c0ecb8bf28eb 10097
Marko Mikulicic 0:c0ecb8bf28eb 10098 if (flags.neg) {
Marko Mikulicic 0:c0ecb8bf28eb 10099 result = -result;
Marko Mikulicic 0:c0ecb8bf28eb 10100 }
Marko Mikulicic 0:c0ecb8bf28eb 10101
Marko Mikulicic 0:c0ecb8bf28eb 10102 if (endptr != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10103 *endptr = (char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 10104 }
Marko Mikulicic 0:c0ecb8bf28eb 10105
Marko Mikulicic 0:c0ecb8bf28eb 10106 return result;
Marko Mikulicic 0:c0ecb8bf28eb 10107 }
Marko Mikulicic 0:c0ecb8bf28eb 10108 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10109 #line 1 "common/coroutine.c"
Marko Mikulicic 0:c0ecb8bf28eb 10110 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10111 /*
Marko Mikulicic 0:c0ecb8bf28eb 10112 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10113 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10114 */
Marko Mikulicic 0:c0ecb8bf28eb 10115
Marko Mikulicic 0:c0ecb8bf28eb 10116 /*
Marko Mikulicic 0:c0ecb8bf28eb 10117 * Module that provides generic macros and functions to implement "coroutines",
Marko Mikulicic 0:c0ecb8bf28eb 10118 * i.e. C code that uses `mbuf` as a stack for function calls.
Marko Mikulicic 0:c0ecb8bf28eb 10119 *
Marko Mikulicic 0:c0ecb8bf28eb 10120 * More info: see the design doc: https://goo.gl/kfcG61
Marko Mikulicic 0:c0ecb8bf28eb 10121 */
Marko Mikulicic 0:c0ecb8bf28eb 10122
Marko Mikulicic 0:c0ecb8bf28eb 10123 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 10124 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 10125
Marko Mikulicic 0:c0ecb8bf28eb 10126 /* Amalgamated: #include "common/coroutine.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10127
Marko Mikulicic 0:c0ecb8bf28eb 10128 /*
Marko Mikulicic 0:c0ecb8bf28eb 10129 * Unwinds stack by 1 function. Used when we're returning from function and
Marko Mikulicic 0:c0ecb8bf28eb 10130 * when an exception is thrown.
Marko Mikulicic 0:c0ecb8bf28eb 10131 */
Marko Mikulicic 0:c0ecb8bf28eb 10132 static void _level_up(struct cr_ctx *p_ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 10133 /* get size of current function's stack data */
Marko Mikulicic 0:c0ecb8bf28eb 10134 size_t locals_size = _CR_CURR_FUNC_LOCALS_SIZE(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10135
Marko Mikulicic 0:c0ecb8bf28eb 10136 /* check stacks underflow */
Marko Mikulicic 0:c0ecb8bf28eb 10137 if (_CR_STACK_FID_UND_CHECK(p_ctx, 1 /*fid*/)) {
Marko Mikulicic 0:c0ecb8bf28eb 10138 p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW;
Marko Mikulicic 0:c0ecb8bf28eb 10139 return;
Marko Mikulicic 0:c0ecb8bf28eb 10140 } else if (_CR_STACK_DATA_UND_CHECK(p_ctx, locals_size)) {
Marko Mikulicic 0:c0ecb8bf28eb 10141 p_ctx->status = CR_RES__ERR_STACK_DATA_UNDERFLOW;
Marko Mikulicic 0:c0ecb8bf28eb 10142 return;
Marko Mikulicic 0:c0ecb8bf28eb 10143 }
Marko Mikulicic 0:c0ecb8bf28eb 10144
Marko Mikulicic 0:c0ecb8bf28eb 10145 /* decrement stacks */
Marko Mikulicic 0:c0ecb8bf28eb 10146 _CR_STACK_DATA_FREE(p_ctx, locals_size);
Marko Mikulicic 0:c0ecb8bf28eb 10147 _CR_STACK_FID_FREE(p_ctx, 1 /*fid*/);
Marko Mikulicic 0:c0ecb8bf28eb 10148 p_ctx->stack_ret.len = p_ctx->cur_fid_idx;
Marko Mikulicic 0:c0ecb8bf28eb 10149
Marko Mikulicic 0:c0ecb8bf28eb 10150 /* if we have exception marker here, adjust cur_fid_idx */
Marko Mikulicic 0:c0ecb8bf28eb 10151 while (CR_CURR_FUNC_C(p_ctx) == CR_FID__TRY_MARKER) {
Marko Mikulicic 0:c0ecb8bf28eb 10152 /* check for stack underflow */
Marko Mikulicic 0:c0ecb8bf28eb 10153 if (_CR_STACK_FID_UND_CHECK(p_ctx, _CR_TRY_SIZE)) {
Marko Mikulicic 0:c0ecb8bf28eb 10154 p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW;
Marko Mikulicic 0:c0ecb8bf28eb 10155 return;
Marko Mikulicic 0:c0ecb8bf28eb 10156 }
Marko Mikulicic 0:c0ecb8bf28eb 10157 _CR_STACK_FID_FREE(p_ctx, _CR_TRY_SIZE);
Marko Mikulicic 0:c0ecb8bf28eb 10158 }
Marko Mikulicic 0:c0ecb8bf28eb 10159 }
Marko Mikulicic 0:c0ecb8bf28eb 10160
Marko Mikulicic 0:c0ecb8bf28eb 10161 enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 10162 if (p_ctx->status != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10163 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10164 } else if (p_ctx->called_fid != CR_FID__NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 10165 /* need to call new function */
Marko Mikulicic 0:c0ecb8bf28eb 10166
Marko Mikulicic 0:c0ecb8bf28eb 10167 size_t locals_size = p_ctx->p_func_descrs[p_ctx->called_fid].locals_size;
Marko Mikulicic 0:c0ecb8bf28eb 10168 /*
Marko Mikulicic 0:c0ecb8bf28eb 10169 * increment stack pointers
Marko Mikulicic 0:c0ecb8bf28eb 10170 */
Marko Mikulicic 0:c0ecb8bf28eb 10171 /* make sure this function has correct `struct cr_func_desc` entry */
Marko Mikulicic 0:c0ecb8bf28eb 10172 assert(locals_size == p_ctx->call_locals_size);
Marko Mikulicic 0:c0ecb8bf28eb 10173 /*
Marko Mikulicic 0:c0ecb8bf28eb 10174 * make sure we haven't mistakenly included "zero-sized" `.._arg_t`
Marko Mikulicic 0:c0ecb8bf28eb 10175 * structure in `.._locals_t` struct
Marko Mikulicic 0:c0ecb8bf28eb 10176 *
Marko Mikulicic 0:c0ecb8bf28eb 10177 * By "zero-sized" I mean `cr_zero_size_type_t`.
Marko Mikulicic 0:c0ecb8bf28eb 10178 */
Marko Mikulicic 0:c0ecb8bf28eb 10179 assert(locals_size < sizeof(cr_zero_size_type_t));
Marko Mikulicic 0:c0ecb8bf28eb 10180
Marko Mikulicic 0:c0ecb8bf28eb 10181 _CR_STACK_DATA_ALLOC(p_ctx, locals_size);
Marko Mikulicic 0:c0ecb8bf28eb 10182 _CR_STACK_RET_ALLOC(p_ctx, 1 /*fid*/);
Marko Mikulicic 0:c0ecb8bf28eb 10183 p_ctx->cur_fid_idx = p_ctx->stack_ret.len;
Marko Mikulicic 0:c0ecb8bf28eb 10184
Marko Mikulicic 0:c0ecb8bf28eb 10185 /* copy arguments to our "stack" (and advance locals stack pointer) */
Marko Mikulicic 0:c0ecb8bf28eb 10186 memcpy(p_ctx->stack_data.buf + p_ctx->stack_data.len - locals_size,
Marko Mikulicic 0:c0ecb8bf28eb 10187 p_ctx->p_arg_retval, p_ctx->call_arg_size);
Marko Mikulicic 0:c0ecb8bf28eb 10188
Marko Mikulicic 0:c0ecb8bf28eb 10189 /* set function id */
Marko Mikulicic 0:c0ecb8bf28eb 10190 CR_CURR_FUNC_C(p_ctx) = p_ctx->called_fid;
Marko Mikulicic 0:c0ecb8bf28eb 10191
Marko Mikulicic 0:c0ecb8bf28eb 10192 /* clear called_fid */
Marko Mikulicic 0:c0ecb8bf28eb 10193 p_ctx->called_fid = CR_FID__NONE;
Marko Mikulicic 0:c0ecb8bf28eb 10194
Marko Mikulicic 0:c0ecb8bf28eb 10195 } else if (p_ctx->need_return) {
Marko Mikulicic 0:c0ecb8bf28eb 10196 /* need to return from the currently running function */
Marko Mikulicic 0:c0ecb8bf28eb 10197
Marko Mikulicic 0:c0ecb8bf28eb 10198 _level_up(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10199 if (p_ctx->status != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10200 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10201 }
Marko Mikulicic 0:c0ecb8bf28eb 10202
Marko Mikulicic 0:c0ecb8bf28eb 10203 p_ctx->need_return = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10204
Marko Mikulicic 0:c0ecb8bf28eb 10205 } else if (p_ctx->need_yield) {
Marko Mikulicic 0:c0ecb8bf28eb 10206 /* need to yield */
Marko Mikulicic 0:c0ecb8bf28eb 10207
Marko Mikulicic 0:c0ecb8bf28eb 10208 p_ctx->need_yield = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10209 p_ctx->status = CR_RES__OK_YIELDED;
Marko Mikulicic 0:c0ecb8bf28eb 10210 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10211
Marko Mikulicic 0:c0ecb8bf28eb 10212 } else if (p_ctx->thrown_exc != CR_EXC_ID__NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 10213 /* exception was thrown */
Marko Mikulicic 0:c0ecb8bf28eb 10214
Marko Mikulicic 0:c0ecb8bf28eb 10215 /* unwind stack until we reach the bottom, or find some try-catch blocks */
Marko Mikulicic 0:c0ecb8bf28eb 10216 do {
Marko Mikulicic 0:c0ecb8bf28eb 10217 _level_up(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10218 if (p_ctx->status != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10219 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10220 }
Marko Mikulicic 0:c0ecb8bf28eb 10221
Marko Mikulicic 0:c0ecb8bf28eb 10222 if (_CR_TRY_MARKER(p_ctx) == CR_FID__TRY_MARKER) {
Marko Mikulicic 0:c0ecb8bf28eb 10223 /* we have some try-catch here, go to the first catch */
Marko Mikulicic 0:c0ecb8bf28eb 10224 CR_CURR_FUNC_C(p_ctx) = _CR_TRY_CATCH_FID(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10225 break;
Marko Mikulicic 0:c0ecb8bf28eb 10226 } else if (CR_CURR_FUNC_C(p_ctx) == CR_FID__NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 10227 /* we've reached the bottom of the stack */
Marko Mikulicic 0:c0ecb8bf28eb 10228 p_ctx->status = CR_RES__ERR_UNCAUGHT_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 10229 break;
Marko Mikulicic 0:c0ecb8bf28eb 10230 }
Marko Mikulicic 0:c0ecb8bf28eb 10231
Marko Mikulicic 0:c0ecb8bf28eb 10232 } while (1);
Marko Mikulicic 0:c0ecb8bf28eb 10233 }
Marko Mikulicic 0:c0ecb8bf28eb 10234
Marko Mikulicic 0:c0ecb8bf28eb 10235 /* remember pointer to current function's locals */
Marko Mikulicic 0:c0ecb8bf28eb 10236 _CR_CUR_FUNC_LOCALS_UPD(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10237
Marko Mikulicic 0:c0ecb8bf28eb 10238 out:
Marko Mikulicic 0:c0ecb8bf28eb 10239 return p_ctx->status;
Marko Mikulicic 0:c0ecb8bf28eb 10240 }
Marko Mikulicic 0:c0ecb8bf28eb 10241
Marko Mikulicic 0:c0ecb8bf28eb 10242 void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval,
Marko Mikulicic 0:c0ecb8bf28eb 10243 size_t arg_retval_size,
Marko Mikulicic 0:c0ecb8bf28eb 10244 const struct cr_func_desc *p_func_descrs) {
Marko Mikulicic 0:c0ecb8bf28eb 10245 /*
Marko Mikulicic 0:c0ecb8bf28eb 10246 * make sure we haven't mistakenly included "zero-sized" `.._arg_t`
Marko Mikulicic 0:c0ecb8bf28eb 10247 * structure in `union user_arg_ret`.
Marko Mikulicic 0:c0ecb8bf28eb 10248 *
Marko Mikulicic 0:c0ecb8bf28eb 10249 * By "zero-sized" I mean `cr_zero_size_type_t`.
Marko Mikulicic 0:c0ecb8bf28eb 10250 */
Marko Mikulicic 0:c0ecb8bf28eb 10251 assert(arg_retval_size < sizeof(cr_zero_size_type_t));
Marko Mikulicic 0:c0ecb8bf28eb 10252 #ifdef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 10253 (void) arg_retval_size;
Marko Mikulicic 0:c0ecb8bf28eb 10254 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10255
Marko Mikulicic 0:c0ecb8bf28eb 10256 memset(p_ctx, 0x00, sizeof(*p_ctx));
Marko Mikulicic 0:c0ecb8bf28eb 10257
Marko Mikulicic 0:c0ecb8bf28eb 10258 p_ctx->p_func_descrs = p_func_descrs;
Marko Mikulicic 0:c0ecb8bf28eb 10259 p_ctx->p_arg_retval = p_arg_retval;
Marko Mikulicic 0:c0ecb8bf28eb 10260
Marko Mikulicic 0:c0ecb8bf28eb 10261 mbuf_init(&p_ctx->stack_data, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10262 mbuf_init(&p_ctx->stack_ret, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10263
Marko Mikulicic 0:c0ecb8bf28eb 10264 mbuf_append(&p_ctx->stack_ret, NULL, 1 /*starting byte for CR_FID__NONE*/);
Marko Mikulicic 0:c0ecb8bf28eb 10265 p_ctx->cur_fid_idx = p_ctx->stack_ret.len;
Marko Mikulicic 0:c0ecb8bf28eb 10266
Marko Mikulicic 0:c0ecb8bf28eb 10267 _CR_CALL_PREPARE(p_ctx, CR_FID__NONE, 0, 0, CR_FID__NONE);
Marko Mikulicic 0:c0ecb8bf28eb 10268 }
Marko Mikulicic 0:c0ecb8bf28eb 10269
Marko Mikulicic 0:c0ecb8bf28eb 10270 void cr_context_free(struct cr_ctx *p_ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 10271 mbuf_free(&p_ctx->stack_data);
Marko Mikulicic 0:c0ecb8bf28eb 10272 mbuf_free(&p_ctx->stack_ret);
Marko Mikulicic 0:c0ecb8bf28eb 10273 }
Marko Mikulicic 0:c0ecb8bf28eb 10274 #ifdef V7_MODULE_LINES
Marko Mikulicic 1:887cf63a2a0b 10275 #line 1 "common/platforms/mbed/mbed_libc.c"
Marko Mikulicic 1:887cf63a2a0b 10276 #endif
Marko Mikulicic 1:887cf63a2a0b 10277 /*
Marko Mikulicic 1:887cf63a2a0b 10278 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 1:887cf63a2a0b 10279 * All rights reserved
Marko Mikulicic 1:887cf63a2a0b 10280 */
Marko Mikulicic 1:887cf63a2a0b 10281
Marko Mikulicic 1:887cf63a2a0b 10282 #if CS_PLATFORM == CS_P_MBED
Marko Mikulicic 1:887cf63a2a0b 10283
Marko Mikulicic 1:887cf63a2a0b 10284 long timezone;
Marko Mikulicic 1:887cf63a2a0b 10285
Marko Mikulicic 1:887cf63a2a0b 10286 #endif /* CS_PLATFORM == CS_P_MBED */
Marko Mikulicic 1:887cf63a2a0b 10287 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10288 #line 1 "v7/builtin/file.c"
Marko Mikulicic 0:c0ecb8bf28eb 10289 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10290 /*
Marko Mikulicic 0:c0ecb8bf28eb 10291 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10292 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10293 */
Marko Mikulicic 0:c0ecb8bf28eb 10294
Marko Mikulicic 0:c0ecb8bf28eb 10295 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10296 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10297 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10298 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10299 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10300 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10301 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10302 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10303 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10304 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10305 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10306 /* Amalgamated: #include "common/cs_dirent.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10307
Marko Mikulicic 0:c0ecb8bf28eb 10308 #if defined(V7_ENABLE_FILE) && !defined(V7_NO_FS)
Marko Mikulicic 0:c0ecb8bf28eb 10309
Marko Mikulicic 0:c0ecb8bf28eb 10310 static const char s_fd_prop[] = "__fd";
Marko Mikulicic 0:c0ecb8bf28eb 10311
Marko Mikulicic 0:c0ecb8bf28eb 10312 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 10313 static FILE *v7_val_to_file(struct v7 *v7, v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 10314 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10315 return (FILE *) v7_get_ptr(v7, val);
Marko Mikulicic 0:c0ecb8bf28eb 10316 }
Marko Mikulicic 0:c0ecb8bf28eb 10317
Marko Mikulicic 0:c0ecb8bf28eb 10318 static v7_val_t v7_file_to_val(struct v7 *v7, FILE *file) {
Marko Mikulicic 0:c0ecb8bf28eb 10319 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10320 return v7_mk_foreign(v7, file);
Marko Mikulicic 0:c0ecb8bf28eb 10321 }
Marko Mikulicic 0:c0ecb8bf28eb 10322
Marko Mikulicic 0:c0ecb8bf28eb 10323 static int v7_is_file_type(v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 10324 return v7_is_foreign(val);
Marko Mikulicic 0:c0ecb8bf28eb 10325 }
Marko Mikulicic 0:c0ecb8bf28eb 10326 #else
Marko Mikulicic 0:c0ecb8bf28eb 10327 FILE *v7_val_to_file(struct v7 *v7, v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 10328 v7_val_t v7_file_to_val(struct v7 *v7, FILE *file);
Marko Mikulicic 0:c0ecb8bf28eb 10329 int v7_is_file_type(v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 10330 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10331
Marko Mikulicic 0:c0ecb8bf28eb 10332 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10333 V7_PRIVATE enum v7_err File_eval(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10334 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10335 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10336
Marko Mikulicic 0:c0ecb8bf28eb 10337 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10338
Marko Mikulicic 0:c0ecb8bf28eb 10339 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10340 const char *s = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10341 if (s == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10342 rcode = v7_throwf(v7, "TypeError", "Invalid string");
Marko Mikulicic 0:c0ecb8bf28eb 10343 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10344 }
Marko Mikulicic 0:c0ecb8bf28eb 10345
Marko Mikulicic 0:c0ecb8bf28eb 10346 v7_set_gc_enabled(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10347 rcode = v7_exec_file(v7, s, res);
Marko Mikulicic 0:c0ecb8bf28eb 10348 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10349 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10350 }
Marko Mikulicic 0:c0ecb8bf28eb 10351 }
Marko Mikulicic 0:c0ecb8bf28eb 10352
Marko Mikulicic 0:c0ecb8bf28eb 10353 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10354 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10355 }
Marko Mikulicic 0:c0ecb8bf28eb 10356
Marko Mikulicic 0:c0ecb8bf28eb 10357 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10358 V7_PRIVATE enum v7_err File_exists(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10359 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10360 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10361
Marko Mikulicic 0:c0ecb8bf28eb 10362 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10363
Marko Mikulicic 0:c0ecb8bf28eb 10364 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10365 const char *fname = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10366 if (fname != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10367 struct stat st;
Marko Mikulicic 0:c0ecb8bf28eb 10368 if (stat(fname, &st) == 0) *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10369 }
Marko Mikulicic 0:c0ecb8bf28eb 10370 }
Marko Mikulicic 0:c0ecb8bf28eb 10371
Marko Mikulicic 0:c0ecb8bf28eb 10372 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10373 }
Marko Mikulicic 0:c0ecb8bf28eb 10374
Marko Mikulicic 0:c0ecb8bf28eb 10375 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10376 static enum v7_err f_read(struct v7 *v7, int all, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10377 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10378 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10379 v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10380
Marko Mikulicic 0:c0ecb8bf28eb 10381 if (v7_is_file_type(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10382 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 10383 char buf[BUFSIZ];
Marko Mikulicic 0:c0ecb8bf28eb 10384 int n;
Marko Mikulicic 0:c0ecb8bf28eb 10385 FILE *fp = v7_val_to_file(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10386
Marko Mikulicic 0:c0ecb8bf28eb 10387 /* Read file contents into mbuf */
Marko Mikulicic 0:c0ecb8bf28eb 10388 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10389 while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10390 mbuf_append(&m, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 10391 if (!all) {
Marko Mikulicic 0:c0ecb8bf28eb 10392 break;
Marko Mikulicic 0:c0ecb8bf28eb 10393 }
Marko Mikulicic 0:c0ecb8bf28eb 10394 }
Marko Mikulicic 0:c0ecb8bf28eb 10395
Marko Mikulicic 0:c0ecb8bf28eb 10396 if (m.len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10397 *res = v7_mk_string(v7, m.buf, m.len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10398 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 10399 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10400 }
Marko Mikulicic 0:c0ecb8bf28eb 10401 }
Marko Mikulicic 0:c0ecb8bf28eb 10402 *res = v7_mk_string(v7, "", 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10403
Marko Mikulicic 0:c0ecb8bf28eb 10404 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10405 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10406 }
Marko Mikulicic 0:c0ecb8bf28eb 10407
Marko Mikulicic 0:c0ecb8bf28eb 10408 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10409 V7_PRIVATE enum v7_err File_obj_read(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10410 return f_read(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 10411 }
Marko Mikulicic 0:c0ecb8bf28eb 10412
Marko Mikulicic 0:c0ecb8bf28eb 10413 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10414 V7_PRIVATE enum v7_err File_obj_write(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10415 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10416 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10417 v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10418 v7_val_t arg1 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10419 size_t n, sent = 0, len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10420
Marko Mikulicic 0:c0ecb8bf28eb 10421 if (v7_is_file_type(arg0) && v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10422 const char *s = v7_get_string(v7, &arg1, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10423 FILE *fp = v7_val_to_file(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10424 while (sent < len && (n = fwrite(s + sent, 1, len - sent, fp)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10425 sent += n;
Marko Mikulicic 0:c0ecb8bf28eb 10426 }
Marko Mikulicic 0:c0ecb8bf28eb 10427 }
Marko Mikulicic 0:c0ecb8bf28eb 10428
Marko Mikulicic 0:c0ecb8bf28eb 10429 *res = v7_mk_number(v7, sent);
Marko Mikulicic 0:c0ecb8bf28eb 10430
Marko Mikulicic 0:c0ecb8bf28eb 10431 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10432 }
Marko Mikulicic 0:c0ecb8bf28eb 10433
Marko Mikulicic 0:c0ecb8bf28eb 10434 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10435 V7_PRIVATE enum v7_err File_obj_close(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10436 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10437 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10438 v7_val_t prop = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10439 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 10440
Marko Mikulicic 0:c0ecb8bf28eb 10441 if (v7_is_file_type(prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 10442 ires = fclose(v7_val_to_file(v7, prop));
Marko Mikulicic 0:c0ecb8bf28eb 10443 }
Marko Mikulicic 0:c0ecb8bf28eb 10444
Marko Mikulicic 0:c0ecb8bf28eb 10445 *res = v7_mk_number(v7, ires);
Marko Mikulicic 0:c0ecb8bf28eb 10446
Marko Mikulicic 0:c0ecb8bf28eb 10447 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10448 }
Marko Mikulicic 0:c0ecb8bf28eb 10449
Marko Mikulicic 0:c0ecb8bf28eb 10450 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10451 V7_PRIVATE enum v7_err File_open(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10452 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10453 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10454 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10455 FILE *fp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10456
Marko Mikulicic 0:c0ecb8bf28eb 10457 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10458 const char *s1 = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10459 const char *s2 = "rb"; /* Open files in read mode by default */
Marko Mikulicic 0:c0ecb8bf28eb 10460
Marko Mikulicic 0:c0ecb8bf28eb 10461 if (v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10462 s2 = v7_get_cstring(v7, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 10463 }
Marko Mikulicic 0:c0ecb8bf28eb 10464
Marko Mikulicic 0:c0ecb8bf28eb 10465 if (s1 == NULL || s2 == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10466 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10467 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10468 }
Marko Mikulicic 0:c0ecb8bf28eb 10469
Marko Mikulicic 0:c0ecb8bf28eb 10470 fp = fopen(s1, s2);
Marko Mikulicic 0:c0ecb8bf28eb 10471 if (fp != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10472 v7_val_t obj = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10473 v7_val_t file_proto = v7_get(
Marko Mikulicic 0:c0ecb8bf28eb 10474 v7, v7_get(v7, v7_get_global(v7), "File", ~0), "prototype", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 10475 v7_set_proto(v7, obj, file_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10476 v7_def(v7, obj, s_fd_prop, sizeof(s_fd_prop) - 1, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 10477 v7_file_to_val(v7, fp));
Marko Mikulicic 0:c0ecb8bf28eb 10478 *res = obj;
Marko Mikulicic 0:c0ecb8bf28eb 10479 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10480 }
Marko Mikulicic 0:c0ecb8bf28eb 10481 }
Marko Mikulicic 0:c0ecb8bf28eb 10482
Marko Mikulicic 0:c0ecb8bf28eb 10483 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10484
Marko Mikulicic 0:c0ecb8bf28eb 10485 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10486 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10487 }
Marko Mikulicic 0:c0ecb8bf28eb 10488
Marko Mikulicic 0:c0ecb8bf28eb 10489 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10490 V7_PRIVATE enum v7_err File_read(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10491 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10492
Marko Mikulicic 0:c0ecb8bf28eb 10493 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10494 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10495 size_t size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10496 char *data = cs_read_file(path, &size);
Marko Mikulicic 0:c0ecb8bf28eb 10497 if (data != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10498 *res = v7_mk_string(v7, data, size, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10499 free(data);
Marko Mikulicic 0:c0ecb8bf28eb 10500 }
Marko Mikulicic 0:c0ecb8bf28eb 10501 }
Marko Mikulicic 0:c0ecb8bf28eb 10502
Marko Mikulicic 0:c0ecb8bf28eb 10503 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10504 }
Marko Mikulicic 0:c0ecb8bf28eb 10505
Marko Mikulicic 0:c0ecb8bf28eb 10506 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10507 V7_PRIVATE enum v7_err File_write(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10508 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10509 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10510 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10511
Marko Mikulicic 0:c0ecb8bf28eb 10512 if (v7_is_string(arg0) && v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10513 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10514 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 10515 const char *buf = v7_get_string(v7, &arg1, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10516 FILE *fp = fopen(path, "wb+");
Marko Mikulicic 0:c0ecb8bf28eb 10517 if (fp != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10518 if (fwrite(buf, 1, len, fp) == len) {
Marko Mikulicic 0:c0ecb8bf28eb 10519 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10520 }
Marko Mikulicic 0:c0ecb8bf28eb 10521 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 10522 }
Marko Mikulicic 0:c0ecb8bf28eb 10523 }
Marko Mikulicic 0:c0ecb8bf28eb 10524
Marko Mikulicic 0:c0ecb8bf28eb 10525 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10526 }
Marko Mikulicic 0:c0ecb8bf28eb 10527
Marko Mikulicic 0:c0ecb8bf28eb 10528 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10529 V7_PRIVATE enum v7_err File_rename(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10530 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10531 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10532 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10533 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 10534
Marko Mikulicic 0:c0ecb8bf28eb 10535 if (v7_is_string(arg0) && v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10536 const char *from = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10537 const char *to = v7_get_cstring(v7, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 10538 if (from == NULL || to == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10539 *res = v7_mk_number(v7, ENOENT);
Marko Mikulicic 0:c0ecb8bf28eb 10540 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10541 }
Marko Mikulicic 0:c0ecb8bf28eb 10542
Marko Mikulicic 0:c0ecb8bf28eb 10543 ires = rename(from, to);
Marko Mikulicic 0:c0ecb8bf28eb 10544 }
Marko Mikulicic 0:c0ecb8bf28eb 10545
Marko Mikulicic 0:c0ecb8bf28eb 10546 *res = v7_mk_number(v7, ires == 0 ? 0 : errno);
Marko Mikulicic 0:c0ecb8bf28eb 10547
Marko Mikulicic 0:c0ecb8bf28eb 10548 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10549 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10550 }
Marko Mikulicic 0:c0ecb8bf28eb 10551
Marko Mikulicic 0:c0ecb8bf28eb 10552 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10553 V7_PRIVATE enum v7_err File_loadJSON(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10554 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10555 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10556
Marko Mikulicic 0:c0ecb8bf28eb 10557 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10558
Marko Mikulicic 0:c0ecb8bf28eb 10559 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10560 const char *file_name = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10561 if (file_name == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10562 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10563 }
Marko Mikulicic 0:c0ecb8bf28eb 10564
Marko Mikulicic 0:c0ecb8bf28eb 10565 rcode = v7_parse_json_file(v7, file_name, res);
Marko Mikulicic 0:c0ecb8bf28eb 10566 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10567 /* swallow exception and return undefined */
Marko Mikulicic 0:c0ecb8bf28eb 10568 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10569 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10570 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10571 }
Marko Mikulicic 0:c0ecb8bf28eb 10572 }
Marko Mikulicic 0:c0ecb8bf28eb 10573
Marko Mikulicic 0:c0ecb8bf28eb 10574 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10575 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10576 }
Marko Mikulicic 0:c0ecb8bf28eb 10577
Marko Mikulicic 0:c0ecb8bf28eb 10578 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10579 V7_PRIVATE enum v7_err File_remove(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10580 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10581 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10582 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 10583
Marko Mikulicic 0:c0ecb8bf28eb 10584 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10585 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10586 if (path == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10587 *res = v7_mk_number(v7, ENOENT);
Marko Mikulicic 0:c0ecb8bf28eb 10588 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10589 }
Marko Mikulicic 0:c0ecb8bf28eb 10590 ires = remove(path);
Marko Mikulicic 0:c0ecb8bf28eb 10591 }
Marko Mikulicic 0:c0ecb8bf28eb 10592 *res = v7_mk_number(v7, ires == 0 ? 0 : errno);
Marko Mikulicic 0:c0ecb8bf28eb 10593
Marko Mikulicic 0:c0ecb8bf28eb 10594 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10595 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10596 }
Marko Mikulicic 0:c0ecb8bf28eb 10597
Marko Mikulicic 0:c0ecb8bf28eb 10598 #if V7_ENABLE__File__list
Marko Mikulicic 0:c0ecb8bf28eb 10599 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10600 V7_PRIVATE enum v7_err File_list(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10601 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10602 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10603
Marko Mikulicic 0:c0ecb8bf28eb 10604 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10605
Marko Mikulicic 0:c0ecb8bf28eb 10606 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10607 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10608 struct dirent *dp;
Marko Mikulicic 0:c0ecb8bf28eb 10609 DIR *dirp;
Marko Mikulicic 0:c0ecb8bf28eb 10610
Marko Mikulicic 0:c0ecb8bf28eb 10611 if (path == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10612 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10613 }
Marko Mikulicic 0:c0ecb8bf28eb 10614
Marko Mikulicic 0:c0ecb8bf28eb 10615 if ((dirp = (opendir(path))) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10616 *res = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10617 while ((dp = readdir(dirp)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10618 /* Do not show current and parent dirs */
Marko Mikulicic 0:c0ecb8bf28eb 10619 if (strcmp((const char *) dp->d_name, ".") == 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 10620 strcmp((const char *) dp->d_name, "..") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10621 continue;
Marko Mikulicic 0:c0ecb8bf28eb 10622 }
Marko Mikulicic 0:c0ecb8bf28eb 10623 /* Add file name to the list */
Marko Mikulicic 0:c0ecb8bf28eb 10624 v7_array_push(v7, *res,
Marko Mikulicic 0:c0ecb8bf28eb 10625 v7_mk_string(v7, (const char *) dp->d_name,
Marko Mikulicic 0:c0ecb8bf28eb 10626 strlen((const char *) dp->d_name), 1));
Marko Mikulicic 0:c0ecb8bf28eb 10627 }
Marko Mikulicic 0:c0ecb8bf28eb 10628 closedir(dirp);
Marko Mikulicic 0:c0ecb8bf28eb 10629 }
Marko Mikulicic 0:c0ecb8bf28eb 10630 }
Marko Mikulicic 0:c0ecb8bf28eb 10631
Marko Mikulicic 0:c0ecb8bf28eb 10632 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10633 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10634 }
Marko Mikulicic 0:c0ecb8bf28eb 10635 #endif /* V7_ENABLE__File__list */
Marko Mikulicic 0:c0ecb8bf28eb 10636
Marko Mikulicic 0:c0ecb8bf28eb 10637 void init_file(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10638 v7_val_t file_obj = v7_mk_object(v7), file_proto = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10639 v7_set(v7, v7_get_global(v7), "File", 4, file_obj);
Marko Mikulicic 0:c0ecb8bf28eb 10640 v7_set(v7, file_obj, "prototype", 9, file_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10641
Marko Mikulicic 0:c0ecb8bf28eb 10642 v7_set_method(v7, file_obj, "eval", File_eval);
Marko Mikulicic 0:c0ecb8bf28eb 10643 v7_set_method(v7, file_obj, "exists", File_exists);
Marko Mikulicic 0:c0ecb8bf28eb 10644 v7_set_method(v7, file_obj, "remove", File_remove);
Marko Mikulicic 0:c0ecb8bf28eb 10645 v7_set_method(v7, file_obj, "rename", File_rename);
Marko Mikulicic 0:c0ecb8bf28eb 10646 v7_set_method(v7, file_obj, "open", File_open);
Marko Mikulicic 0:c0ecb8bf28eb 10647 v7_set_method(v7, file_obj, "read", File_read);
Marko Mikulicic 0:c0ecb8bf28eb 10648 v7_set_method(v7, file_obj, "write", File_write);
Marko Mikulicic 0:c0ecb8bf28eb 10649 v7_set_method(v7, file_obj, "loadJSON", File_loadJSON);
Marko Mikulicic 0:c0ecb8bf28eb 10650 #if V7_ENABLE__File__list
Marko Mikulicic 0:c0ecb8bf28eb 10651 v7_set_method(v7, file_obj, "list", File_list);
Marko Mikulicic 0:c0ecb8bf28eb 10652 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10653
Marko Mikulicic 0:c0ecb8bf28eb 10654 v7_set_method(v7, file_proto, "close", File_obj_close);
Marko Mikulicic 0:c0ecb8bf28eb 10655 v7_set_method(v7, file_proto, "read", File_obj_read);
Marko Mikulicic 0:c0ecb8bf28eb 10656 v7_set_method(v7, file_proto, "write", File_obj_write);
Marko Mikulicic 0:c0ecb8bf28eb 10657
Marko Mikulicic 0:c0ecb8bf28eb 10658 #if V7_ENABLE__File__require
Marko Mikulicic 0:c0ecb8bf28eb 10659 v7_def(v7, v7_get_global(v7), "_modcache", ~0, 0, v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 10660 if (v7_exec(v7,
Marko Mikulicic 0:c0ecb8bf28eb 10661 "function require(m) { "
Marko Mikulicic 0:c0ecb8bf28eb 10662 " if (m in _modcache) { return _modcache[m]; }"
Marko Mikulicic 0:c0ecb8bf28eb 10663 " var module = {exports:{}};"
Marko Mikulicic 0:c0ecb8bf28eb 10664 " File.eval(m);"
Marko Mikulicic 0:c0ecb8bf28eb 10665 " return (_modcache[m] = module.exports)"
Marko Mikulicic 0:c0ecb8bf28eb 10666 " }",
Marko Mikulicic 0:c0ecb8bf28eb 10667 NULL) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10668 /* TODO(mkm): percolate failure */
Marko Mikulicic 0:c0ecb8bf28eb 10669 }
Marko Mikulicic 0:c0ecb8bf28eb 10670 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10671 }
Marko Mikulicic 0:c0ecb8bf28eb 10672 #else
Marko Mikulicic 0:c0ecb8bf28eb 10673 void init_file(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10674 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10675 }
Marko Mikulicic 0:c0ecb8bf28eb 10676 #endif /* NO_LIBC */
Marko Mikulicic 0:c0ecb8bf28eb 10677 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10678 #line 1 "v7/builtin/socket.c"
Marko Mikulicic 0:c0ecb8bf28eb 10679 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10680 /*
Marko Mikulicic 0:c0ecb8bf28eb 10681 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10682 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10683 */
Marko Mikulicic 0:c0ecb8bf28eb 10684
Marko Mikulicic 0:c0ecb8bf28eb 10685 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10686 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10687 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10688 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10689 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10690 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10691 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10692 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10693
Marko Mikulicic 0:c0ecb8bf28eb 10694 #ifdef V7_ENABLE_SOCKET
Marko Mikulicic 0:c0ecb8bf28eb 10695
Marko Mikulicic 0:c0ecb8bf28eb 10696 #ifdef __WATCOM__
Marko Mikulicic 0:c0ecb8bf28eb 10697 #define SOMAXCONN 128
Marko Mikulicic 0:c0ecb8bf28eb 10698 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10699
Marko Mikulicic 0:c0ecb8bf28eb 10700 #ifndef RECV_BUF_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 10701 #define RECV_BUF_SIZE 1024
Marko Mikulicic 0:c0ecb8bf28eb 10702 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10703
Marko Mikulicic 0:c0ecb8bf28eb 10704 static const char s_sock_prop[] = "__sock";
Marko Mikulicic 0:c0ecb8bf28eb 10705
Marko Mikulicic 0:c0ecb8bf28eb 10706 static uint32_t s_resolve(struct v7 *v7, v7_val_t ip_address) {
Marko Mikulicic 0:c0ecb8bf28eb 10707 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 10708 const char *s = v7_get_string(v7, &ip_address, &n);
Marko Mikulicic 0:c0ecb8bf28eb 10709 struct hostent *he = gethostbyname(s);
Marko Mikulicic 0:c0ecb8bf28eb 10710 return he == NULL ? 0 : *(uint32_t *) he->h_addr_list[0];
Marko Mikulicic 0:c0ecb8bf28eb 10711 }
Marko Mikulicic 0:c0ecb8bf28eb 10712
Marko Mikulicic 0:c0ecb8bf28eb 10713 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10714 static enum v7_err s_fd_to_sock_obj(struct v7 *v7, sock_t fd, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10715 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10716 v7_val_t sock_proto =
Marko Mikulicic 0:c0ecb8bf28eb 10717 v7_get(v7, v7_get(v7, v7_get_global(v7), "Socket", ~0), "prototype", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 10718
Marko Mikulicic 0:c0ecb8bf28eb 10719 *res = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10720 v7_set_proto(v7, *res, sock_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10721 v7_def(v7, *res, s_sock_prop, sizeof(s_sock_prop) - 1, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 10722 v7_mk_number(v7, fd));
Marko Mikulicic 0:c0ecb8bf28eb 10723
Marko Mikulicic 0:c0ecb8bf28eb 10724 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10725 }
Marko Mikulicic 0:c0ecb8bf28eb 10726
Marko Mikulicic 0:c0ecb8bf28eb 10727 /* Socket.connect(host, port [, is_udp]) -> socket_object */
Marko Mikulicic 0:c0ecb8bf28eb 10728 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10729 V7_PRIVATE enum v7_err Socket_connect(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10730 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10731 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10732 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10733 v7_val_t arg2 = v7_arg(v7, 2);
Marko Mikulicic 0:c0ecb8bf28eb 10734
Marko Mikulicic 0:c0ecb8bf28eb 10735 if (v7_is_number(arg1) && v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10736 struct sockaddr_in sin;
Marko Mikulicic 0:c0ecb8bf28eb 10737 sock_t sock =
Marko Mikulicic 0:c0ecb8bf28eb 10738 socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10739 memset(&sin, 0, sizeof(sin));
Marko Mikulicic 0:c0ecb8bf28eb 10740 sin.sin_family = AF_INET;
Marko Mikulicic 0:c0ecb8bf28eb 10741 sin.sin_addr.s_addr = s_resolve(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10742 sin.sin_port = htons((uint16_t) v7_get_double(v7, arg1));
Marko Mikulicic 0:c0ecb8bf28eb 10743 if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10744 closesocket(sock);
Marko Mikulicic 0:c0ecb8bf28eb 10745 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10746 rcode = s_fd_to_sock_obj(v7, sock, res);
Marko Mikulicic 0:c0ecb8bf28eb 10747 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10748 }
Marko Mikulicic 0:c0ecb8bf28eb 10749 }
Marko Mikulicic 0:c0ecb8bf28eb 10750
Marko Mikulicic 0:c0ecb8bf28eb 10751 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10752
Marko Mikulicic 0:c0ecb8bf28eb 10753 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10754 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10755 }
Marko Mikulicic 0:c0ecb8bf28eb 10756
Marko Mikulicic 0:c0ecb8bf28eb 10757 /* Socket.listen(port [, ip_address [,is_udp]]) -> sock */
Marko Mikulicic 0:c0ecb8bf28eb 10758 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10759 V7_PRIVATE enum v7_err Socket_listen(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10760 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10761 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10762 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10763 v7_val_t arg2 = v7_arg(v7, 2);
Marko Mikulicic 0:c0ecb8bf28eb 10764
Marko Mikulicic 0:c0ecb8bf28eb 10765 if (v7_is_number(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10766 struct sockaddr_in sin;
Marko Mikulicic 0:c0ecb8bf28eb 10767 int on = 1;
Marko Mikulicic 0:c0ecb8bf28eb 10768 sock_t sock =
Marko Mikulicic 0:c0ecb8bf28eb 10769 socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10770 memset(&sin, 0, sizeof(sin));
Marko Mikulicic 0:c0ecb8bf28eb 10771 sin.sin_family = AF_INET;
Marko Mikulicic 0:c0ecb8bf28eb 10772 sin.sin_port = htons((uint16_t) v7_get_double(v7, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 10773 if (v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10774 sin.sin_addr.s_addr = s_resolve(v7, arg1);
Marko Mikulicic 0:c0ecb8bf28eb 10775 }
Marko Mikulicic 0:c0ecb8bf28eb 10776
Marko Mikulicic 0:c0ecb8bf28eb 10777 #if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)
Marko Mikulicic 0:c0ecb8bf28eb 10778 /* "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" http://goo.gl/RmrFTm */
Marko Mikulicic 0:c0ecb8bf28eb 10779 setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &on, sizeof(on));
Marko Mikulicic 0:c0ecb8bf28eb 10780 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10781
Marko Mikulicic 0:c0ecb8bf28eb 10782 #if !defined(_WIN32) || defined(SO_EXCLUSIVEADDRUSE)
Marko Mikulicic 0:c0ecb8bf28eb 10783 /*
Marko Mikulicic 0:c0ecb8bf28eb 10784 * SO_RESUSEADDR is not enabled on Windows because the semantics of
Marko Mikulicic 0:c0ecb8bf28eb 10785 * SO_REUSEADDR on UNIX and Windows is different. On Windows,
Marko Mikulicic 0:c0ecb8bf28eb 10786 * SO_REUSEADDR allows to bind a socket to a port without error even if
Marko Mikulicic 0:c0ecb8bf28eb 10787 * the port is already open by another program. This is not the behavior
Marko Mikulicic 0:c0ecb8bf28eb 10788 * SO_REUSEADDR was designed for, and leads to hard-to-track failure
Marko Mikulicic 0:c0ecb8bf28eb 10789 * scenarios. Therefore, SO_REUSEADDR was disabled on Windows unless
Marko Mikulicic 0:c0ecb8bf28eb 10790 * SO_EXCLUSIVEADDRUSE is supported and set on a socket.
Marko Mikulicic 0:c0ecb8bf28eb 10791 */
Marko Mikulicic 0:c0ecb8bf28eb 10792 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on));
Marko Mikulicic 0:c0ecb8bf28eb 10793 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10794
Marko Mikulicic 0:c0ecb8bf28eb 10795 if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10796 listen(sock, SOMAXCONN);
Marko Mikulicic 0:c0ecb8bf28eb 10797 rcode = s_fd_to_sock_obj(v7, sock, res);
Marko Mikulicic 0:c0ecb8bf28eb 10798 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10799 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10800 closesocket(sock);
Marko Mikulicic 0:c0ecb8bf28eb 10801 }
Marko Mikulicic 0:c0ecb8bf28eb 10802 }
Marko Mikulicic 0:c0ecb8bf28eb 10803
Marko Mikulicic 0:c0ecb8bf28eb 10804 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10805
Marko Mikulicic 0:c0ecb8bf28eb 10806 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10807 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10808 }
Marko Mikulicic 0:c0ecb8bf28eb 10809
Marko Mikulicic 0:c0ecb8bf28eb 10810 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10811 V7_PRIVATE enum v7_err Socket_accept(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10812 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10813 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10814 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10815
Marko Mikulicic 0:c0ecb8bf28eb 10816 if (v7_is_number(prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 10817 struct sockaddr_in sin;
Marko Mikulicic 0:c0ecb8bf28eb 10818 socklen_t len = sizeof(sin);
Marko Mikulicic 0:c0ecb8bf28eb 10819 sock_t sock = (sock_t) v7_get_double(v7, prop);
Marko Mikulicic 0:c0ecb8bf28eb 10820 sock_t fd = accept(sock, (struct sockaddr *) &sin, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10821 if (fd != INVALID_SOCKET) {
Marko Mikulicic 0:c0ecb8bf28eb 10822 rcode = s_fd_to_sock_obj(v7, fd, res);
Marko Mikulicic 0:c0ecb8bf28eb 10823 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10824 char *remote_host = inet_ntoa(sin.sin_addr);
Marko Mikulicic 0:c0ecb8bf28eb 10825 v7_set(v7, *res, "remoteHost", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 10826 v7_mk_string(v7, remote_host, ~0, 1));
Marko Mikulicic 0:c0ecb8bf28eb 10827 }
Marko Mikulicic 0:c0ecb8bf28eb 10828 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10829 }
Marko Mikulicic 0:c0ecb8bf28eb 10830 }
Marko Mikulicic 0:c0ecb8bf28eb 10831 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10832
Marko Mikulicic 0:c0ecb8bf28eb 10833 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10834 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10835 }
Marko Mikulicic 0:c0ecb8bf28eb 10836
Marko Mikulicic 0:c0ecb8bf28eb 10837 /* sock.close() -> errno */
Marko Mikulicic 0:c0ecb8bf28eb 10838 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10839 V7_PRIVATE enum v7_err Socket_close(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10840 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10841 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10842 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10843 *res = v7_mk_number(v7, closesocket((sock_t) v7_get_double(v7, prop)));
Marko Mikulicic 0:c0ecb8bf28eb 10844
Marko Mikulicic 0:c0ecb8bf28eb 10845 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10846 }
Marko Mikulicic 0:c0ecb8bf28eb 10847
Marko Mikulicic 0:c0ecb8bf28eb 10848 /* sock.recv() -> string */
Marko Mikulicic 0:c0ecb8bf28eb 10849 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10850 static enum v7_err s_recv(struct v7 *v7, int all, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10851 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10852 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10853 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10854
Marko Mikulicic 0:c0ecb8bf28eb 10855 if (v7_is_number(prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 10856 char buf[RECV_BUF_SIZE];
Marko Mikulicic 0:c0ecb8bf28eb 10857 sock_t sock = (sock_t) v7_get_double(v7, prop);
Marko Mikulicic 0:c0ecb8bf28eb 10858 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 10859 int n;
Marko Mikulicic 0:c0ecb8bf28eb 10860
Marko Mikulicic 0:c0ecb8bf28eb 10861 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10862 while ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10863 mbuf_append(&m, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 10864 if (!all) {
Marko Mikulicic 0:c0ecb8bf28eb 10865 break;
Marko Mikulicic 0:c0ecb8bf28eb 10866 }
Marko Mikulicic 0:c0ecb8bf28eb 10867 }
Marko Mikulicic 0:c0ecb8bf28eb 10868
Marko Mikulicic 0:c0ecb8bf28eb 10869 if (n <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10870 closesocket(sock);
Marko Mikulicic 0:c0ecb8bf28eb 10871 v7_def(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1,
Marko Mikulicic 0:c0ecb8bf28eb 10872 V7_DESC_ENUMERABLE(0), v7_mk_number(v7, INVALID_SOCKET));
Marko Mikulicic 0:c0ecb8bf28eb 10873 }
Marko Mikulicic 0:c0ecb8bf28eb 10874
Marko Mikulicic 0:c0ecb8bf28eb 10875 if (m.len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10876 *res = v7_mk_string(v7, m.buf, m.len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10877 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 10878 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10879 }
Marko Mikulicic 0:c0ecb8bf28eb 10880 }
Marko Mikulicic 0:c0ecb8bf28eb 10881
Marko Mikulicic 0:c0ecb8bf28eb 10882 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10883
Marko Mikulicic 0:c0ecb8bf28eb 10884 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10885 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10886 }
Marko Mikulicic 0:c0ecb8bf28eb 10887
Marko Mikulicic 0:c0ecb8bf28eb 10888 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10889 V7_PRIVATE enum v7_err Socket_recvAll(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10890 return s_recv(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 10891 }
Marko Mikulicic 0:c0ecb8bf28eb 10892
Marko Mikulicic 0:c0ecb8bf28eb 10893 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10894 V7_PRIVATE enum v7_err Socket_recv(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10895 return s_recv(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 10896 }
Marko Mikulicic 0:c0ecb8bf28eb 10897
Marko Mikulicic 0:c0ecb8bf28eb 10898 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10899 V7_PRIVATE enum v7_err Socket_send(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10900 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10901 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10902 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10903 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10904 size_t len, sent = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10905
Marko Mikulicic 0:c0ecb8bf28eb 10906 if (v7_is_number(prop) && v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10907 const char *s = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10908 sock_t sock = (sock_t) v7_get_double(v7, prop);
Marko Mikulicic 0:c0ecb8bf28eb 10909 int n;
Marko Mikulicic 0:c0ecb8bf28eb 10910
Marko Mikulicic 0:c0ecb8bf28eb 10911 while (sent < len && (n = send(sock, s + sent, len - sent, 0)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10912 sent += n;
Marko Mikulicic 0:c0ecb8bf28eb 10913 }
Marko Mikulicic 0:c0ecb8bf28eb 10914 }
Marko Mikulicic 0:c0ecb8bf28eb 10915
Marko Mikulicic 0:c0ecb8bf28eb 10916 *res = v7_mk_number(v7, sent);
Marko Mikulicic 0:c0ecb8bf28eb 10917
Marko Mikulicic 0:c0ecb8bf28eb 10918 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10919 }
Marko Mikulicic 0:c0ecb8bf28eb 10920
Marko Mikulicic 0:c0ecb8bf28eb 10921 void init_socket(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10922 v7_val_t socket_obj = v7_mk_object(v7), sock_proto = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10923
Marko Mikulicic 0:c0ecb8bf28eb 10924 v7_set(v7, v7_get_global(v7), "Socket", 6, socket_obj);
Marko Mikulicic 0:c0ecb8bf28eb 10925 sock_proto = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10926 v7_set(v7, socket_obj, "prototype", 9, sock_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10927
Marko Mikulicic 0:c0ecb8bf28eb 10928 v7_set_method(v7, socket_obj, "connect", Socket_connect);
Marko Mikulicic 0:c0ecb8bf28eb 10929 v7_set_method(v7, socket_obj, "listen", Socket_listen);
Marko Mikulicic 0:c0ecb8bf28eb 10930
Marko Mikulicic 0:c0ecb8bf28eb 10931 v7_set_method(v7, sock_proto, "accept", Socket_accept);
Marko Mikulicic 0:c0ecb8bf28eb 10932 v7_set_method(v7, sock_proto, "send", Socket_send);
Marko Mikulicic 0:c0ecb8bf28eb 10933 v7_set_method(v7, sock_proto, "recv", Socket_recv);
Marko Mikulicic 0:c0ecb8bf28eb 10934 v7_set_method(v7, sock_proto, "recvAll", Socket_recvAll);
Marko Mikulicic 0:c0ecb8bf28eb 10935 v7_set_method(v7, sock_proto, "close", Socket_close);
Marko Mikulicic 0:c0ecb8bf28eb 10936
Marko Mikulicic 0:c0ecb8bf28eb 10937 #ifdef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 10938 {
Marko Mikulicic 0:c0ecb8bf28eb 10939 WSADATA data;
Marko Mikulicic 0:c0ecb8bf28eb 10940 WSAStartup(MAKEWORD(2, 2), &data);
Marko Mikulicic 0:c0ecb8bf28eb 10941 /* TODO(alashkin): add WSACleanup call */
Marko Mikulicic 0:c0ecb8bf28eb 10942 }
Marko Mikulicic 0:c0ecb8bf28eb 10943 #else
Marko Mikulicic 0:c0ecb8bf28eb 10944 signal(SIGPIPE, SIG_IGN);
Marko Mikulicic 0:c0ecb8bf28eb 10945 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10946 }
Marko Mikulicic 0:c0ecb8bf28eb 10947 #else
Marko Mikulicic 0:c0ecb8bf28eb 10948 void init_socket(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10949 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10950 }
Marko Mikulicic 0:c0ecb8bf28eb 10951 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10952 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10953 #line 1 "v7/builtin/crypto.c"
Marko Mikulicic 0:c0ecb8bf28eb 10954 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10955 /*
Marko Mikulicic 0:c0ecb8bf28eb 10956 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10957 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10958 */
Marko Mikulicic 0:c0ecb8bf28eb 10959
Marko Mikulicic 0:c0ecb8bf28eb 10960 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 10961 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 10962
Marko Mikulicic 0:c0ecb8bf28eb 10963 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10964 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10965 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10966 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10967 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10968 /* Amalgamated: #include "common/md5.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10969 /* Amalgamated: #include "common/sha1.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10970 /* Amalgamated: #include "common/base64.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10971
Marko Mikulicic 0:c0ecb8bf28eb 10972 #ifdef V7_ENABLE_CRYPTO
Marko Mikulicic 0:c0ecb8bf28eb 10973
Marko Mikulicic 0:c0ecb8bf28eb 10974 typedef void (*b64_func_t)(const unsigned char *, int, char *);
Marko Mikulicic 0:c0ecb8bf28eb 10975
Marko Mikulicic 0:c0ecb8bf28eb 10976 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10977 static enum v7_err b64_transform(struct v7 *v7, b64_func_t func, double mult,
Marko Mikulicic 0:c0ecb8bf28eb 10978 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10979 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10980 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10981 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10982
Marko Mikulicic 0:c0ecb8bf28eb 10983 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10984 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 10985 const char *s = v7_get_string(v7, &arg0, &n);
Marko Mikulicic 0:c0ecb8bf28eb 10986 char *buf = (char *) malloc(n * mult + 4);
Marko Mikulicic 0:c0ecb8bf28eb 10987 if (buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10988 func((const unsigned char *) s, (int) n, buf);
Marko Mikulicic 0:c0ecb8bf28eb 10989 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 10990 free(buf);
Marko Mikulicic 0:c0ecb8bf28eb 10991 }
Marko Mikulicic 0:c0ecb8bf28eb 10992 }
Marko Mikulicic 0:c0ecb8bf28eb 10993
Marko Mikulicic 0:c0ecb8bf28eb 10994 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10995 }
Marko Mikulicic 0:c0ecb8bf28eb 10996
Marko Mikulicic 0:c0ecb8bf28eb 10997 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10998 V7_PRIVATE enum v7_err Crypto_base64_decode(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10999 return b64_transform(v7, (b64_func_t) cs_base64_decode, 0.75, res);
Marko Mikulicic 0:c0ecb8bf28eb 11000 }
Marko Mikulicic 0:c0ecb8bf28eb 11001
Marko Mikulicic 0:c0ecb8bf28eb 11002 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 11003 V7_PRIVATE enum v7_err Crypto_base64_encode(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 11004 return b64_transform(v7, cs_base64_encode, 1.5, res);
Marko Mikulicic 0:c0ecb8bf28eb 11005 }
Marko Mikulicic 0:c0ecb8bf28eb 11006
Marko Mikulicic 0:c0ecb8bf28eb 11007 static void v7_md5(const char *data, size_t len, char buf[16]) {
Marko Mikulicic 0:c0ecb8bf28eb 11008 MD5_CTX ctx;
Marko Mikulicic 0:c0ecb8bf28eb 11009 MD5_Init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 11010 MD5_Update(&ctx, (unsigned char *) data, len);
Marko Mikulicic 0:c0ecb8bf28eb 11011 MD5_Final((unsigned char *) buf, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 11012 }
Marko Mikulicic 0:c0ecb8bf28eb 11013
Marko Mikulicic 0:c0ecb8bf28eb 11014 static void v7_sha1(const char *data, size_t len, char buf[20]) {
Marko Mikulicic 0:c0ecb8bf28eb 11015 cs_sha1_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 11016 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 11017 cs_sha1_update(&ctx, (unsigned char *) data, len);
Marko Mikulicic 0:c0ecb8bf28eb 11018 cs_sha1_final((unsigned char *) buf, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 11019 }
Marko Mikulicic 0:c0ecb8bf28eb 11020
Marko Mikulicic 0:c0ecb8bf28eb 11021 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 11022 V7_PRIVATE enum v7_err Crypto_md5(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 11023 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 11024 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 11025
Marko Mikulicic 0:c0ecb8bf28eb 11026 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 11027 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 11028 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 11029 char buf[16];
Marko Mikulicic 0:c0ecb8bf28eb 11030 v7_md5(data, len, buf);
Marko Mikulicic 0:c0ecb8bf28eb 11031 *res = v7_mk_string(v7, buf, sizeof(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 11032 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 11033 }
Marko Mikulicic 0:c0ecb8bf28eb 11034
Marko Mikulicic 0:c0ecb8bf28eb 11035 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11036
Marko Mikulicic 0:c0ecb8bf28eb 11037 clean:
Marko Mikulicic 0:c0ecb8bf28eb 11038 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 11039 }
Marko Mikulicic 0:c0ecb8bf28eb 11040
Marko Mikulicic 0:c0ecb8bf28eb 11041 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 11042 V7_PRIVATE enum v7_err Crypto_md5_hex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 11043 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 11044 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 11045
Marko Mikulicic 0:c0ecb8bf28eb 11046 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 11047 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 11048 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 11049 char hash[16], buf[sizeof(hash) * 2 + 1];
Marko Mikulicic 0:c0ecb8bf28eb 11050 v7_md5(data, len, hash);
Marko Mikulicic 0:c0ecb8bf28eb 11051 cs_to_hex(buf, (unsigned char *) hash, sizeof(hash));
Marko Mikulicic 0:c0ecb8bf28eb 11052 *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 11053 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 11054 }
Marko Mikulicic 0:c0ecb8bf28eb 11055 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11056
Marko Mikulicic 0:c0ecb8bf28eb 11057 clean:
Marko Mikulicic 0:c0ecb8bf28eb 11058 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 11059 }
Marko Mikulicic 0:c0ecb8bf28eb 11060
Marko Mikulicic 0:c0ecb8bf28eb 11061 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 11062 V7_PRIVATE enum v7_err Crypto_sha1(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 11063 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 11064 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 11065
Marko Mikulicic 0:c0ecb8bf28eb 11066 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 11067 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 11068 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 11069 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 11070 v7_sha1(data, len, buf);
Marko Mikulicic 0:c0ecb8bf28eb 11071 *res = v7_mk_string(v7, buf, sizeof(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 11072 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 11073 }
Marko Mikulicic 0:c0ecb8bf28eb 11074 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11075
Marko Mikulicic 0:c0ecb8bf28eb 11076 clean:
Marko Mikulicic 0:c0ecb8bf28eb 11077 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 11078 }
Marko Mikulicic 0:c0ecb8bf28eb 11079
Marko Mikulicic 0:c0ecb8bf28eb 11080 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 11081 V7_PRIVATE enum v7_err Crypto_sha1_hex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 11082 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 11083 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 11084
Marko Mikulicic 0:c0ecb8bf28eb 11085 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 11086 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 11087 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 11088 char hash[20], buf[sizeof(hash) * 2 + 1];
Marko Mikulicic 0:c0ecb8bf28eb 11089 v7_sha1(data, len, hash);
Marko Mikulicic 0:c0ecb8bf28eb 11090 cs_to_hex(buf, (unsigned char *) hash, sizeof(hash));
Marko Mikulicic 0:c0ecb8bf28eb 11091 *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 11092 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 11093 }
Marko Mikulicic 0:c0ecb8bf28eb 11094 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11095
Marko Mikulicic 0:c0ecb8bf28eb 11096 clean:
Marko Mikulicic 0:c0ecb8bf28eb 11097 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 11098 }
Marko Mikulicic 0:c0ecb8bf28eb 11099 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11100
Marko Mikulicic 0:c0ecb8bf28eb 11101 void init_crypto(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 11102 #ifdef V7_ENABLE_CRYPTO
Marko Mikulicic 0:c0ecb8bf28eb 11103 v7_val_t obj = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 11104 v7_set(v7, v7_get_global(v7), "Crypto", 6, obj);
Marko Mikulicic 0:c0ecb8bf28eb 11105 v7_set_method(v7, obj, "md5", Crypto_md5);
Marko Mikulicic 0:c0ecb8bf28eb 11106 v7_set_method(v7, obj, "md5_hex", Crypto_md5_hex);
Marko Mikulicic 0:c0ecb8bf28eb 11107 v7_set_method(v7, obj, "sha1", Crypto_sha1);
Marko Mikulicic 0:c0ecb8bf28eb 11108 v7_set_method(v7, obj, "sha1_hex", Crypto_sha1_hex);
Marko Mikulicic 0:c0ecb8bf28eb 11109 v7_set_method(v7, obj, "base64_encode", Crypto_base64_encode);
Marko Mikulicic 0:c0ecb8bf28eb 11110 v7_set_method(v7, obj, "base64_decode", Crypto_base64_decode);
Marko Mikulicic 0:c0ecb8bf28eb 11111 #else
Marko Mikulicic 0:c0ecb8bf28eb 11112 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 11113 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11114 }
Marko Mikulicic 0:c0ecb8bf28eb 11115 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 11116 #line 1 "v7/src/varint.c"
Marko Mikulicic 0:c0ecb8bf28eb 11117 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11118 /*
Marko Mikulicic 0:c0ecb8bf28eb 11119 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 11120 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 11121 */
Marko Mikulicic 0:c0ecb8bf28eb 11122
Marko Mikulicic 0:c0ecb8bf28eb 11123 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11124 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11125
Marko Mikulicic 0:c0ecb8bf28eb 11126 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 11127 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 11128 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 11129
Marko Mikulicic 0:c0ecb8bf28eb 11130 /*
Marko Mikulicic 0:c0ecb8bf28eb 11131 * Strings in AST are encoded as tuples (length, string).
Marko Mikulicic 0:c0ecb8bf28eb 11132 * Length is variable-length: if high bit is set in a byte, next byte is used.
Marko Mikulicic 0:c0ecb8bf28eb 11133 * Maximum string length with such encoding is 2 ^ (7 * 4) == 256 MiB,
Marko Mikulicic 0:c0ecb8bf28eb 11134 * assuming that sizeof(size_t) == 4.
Marko Mikulicic 0:c0ecb8bf28eb 11135 * Small string length (less then 128 bytes) is encoded in 1 byte.
Marko Mikulicic 0:c0ecb8bf28eb 11136 */
Marko Mikulicic 0:c0ecb8bf28eb 11137 V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen) {
Marko Mikulicic 0:c0ecb8bf28eb 11138 size_t i = 0, string_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 11139
Marko Mikulicic 0:c0ecb8bf28eb 11140 do {
Marko Mikulicic 0:c0ecb8bf28eb 11141 /*
Marko Mikulicic 0:c0ecb8bf28eb 11142 * Each byte of varint contains 7 bits, in little endian order.
Marko Mikulicic 0:c0ecb8bf28eb 11143 * MSB is a continuation bit: it tells whether next byte is used.
Marko Mikulicic 0:c0ecb8bf28eb 11144 */
Marko Mikulicic 0:c0ecb8bf28eb 11145 string_len |= (p[i] & 0x7f) << (7 * i);
Marko Mikulicic 0:c0ecb8bf28eb 11146 /*
Marko Mikulicic 0:c0ecb8bf28eb 11147 * First we increment i, then check whether it is within boundary and
Marko Mikulicic 0:c0ecb8bf28eb 11148 * whether decoded byte had continuation bit set.
Marko Mikulicic 0:c0ecb8bf28eb 11149 */
Marko Mikulicic 0:c0ecb8bf28eb 11150 } while (++i < sizeof(size_t) && (p[i - 1] & 0x80));
Marko Mikulicic 0:c0ecb8bf28eb 11151 *llen = i;
Marko Mikulicic 0:c0ecb8bf28eb 11152
Marko Mikulicic 0:c0ecb8bf28eb 11153 return string_len;
Marko Mikulicic 0:c0ecb8bf28eb 11154 }
Marko Mikulicic 0:c0ecb8bf28eb 11155
Marko Mikulicic 0:c0ecb8bf28eb 11156 /* Return number of bytes to store length */
Marko Mikulicic 0:c0ecb8bf28eb 11157 V7_PRIVATE int calc_llen(size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 11158 int n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 11159
Marko Mikulicic 0:c0ecb8bf28eb 11160 do {
Marko Mikulicic 0:c0ecb8bf28eb 11161 n++;
Marko Mikulicic 0:c0ecb8bf28eb 11162 } while (len >>= 7);
Marko Mikulicic 0:c0ecb8bf28eb 11163
Marko Mikulicic 0:c0ecb8bf28eb 11164 return n;
Marko Mikulicic 0:c0ecb8bf28eb 11165 }
Marko Mikulicic 0:c0ecb8bf28eb 11166
Marko Mikulicic 0:c0ecb8bf28eb 11167 V7_PRIVATE int encode_varint(size_t len, unsigned char *p) {
Marko Mikulicic 0:c0ecb8bf28eb 11168 int i, llen = calc_llen(len);
Marko Mikulicic 0:c0ecb8bf28eb 11169
Marko Mikulicic 0:c0ecb8bf28eb 11170 for (i = 0; i < llen; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 11171 p[i] = (len & 0x7f) | (i < llen - 1 ? 0x80 : 0);
Marko Mikulicic 0:c0ecb8bf28eb 11172 len >>= 7;
Marko Mikulicic 0:c0ecb8bf28eb 11173 }
Marko Mikulicic 0:c0ecb8bf28eb 11174
Marko Mikulicic 0:c0ecb8bf28eb 11175 return llen;
Marko Mikulicic 0:c0ecb8bf28eb 11176 }
Marko Mikulicic 0:c0ecb8bf28eb 11177
Marko Mikulicic 0:c0ecb8bf28eb 11178 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 11179 }
Marko Mikulicic 0:c0ecb8bf28eb 11180 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 11181 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 11182 #line 1 "v7/src/tokenizer.c"
Marko Mikulicic 0:c0ecb8bf28eb 11183 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11184 /*
Marko Mikulicic 0:c0ecb8bf28eb 11185 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 11186 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 11187 */
Marko Mikulicic 0:c0ecb8bf28eb 11188
Marko Mikulicic 0:c0ecb8bf28eb 11189 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11190 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11191
Marko Mikulicic 0:c0ecb8bf28eb 11192 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11193 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11194
Marko Mikulicic 0:c0ecb8bf28eb 11195 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 11196
Marko Mikulicic 0:c0ecb8bf28eb 11197 /*
Marko Mikulicic 0:c0ecb8bf28eb 11198 * NOTE(lsm): Must be in the same order as enum for keywords. See comment
Marko Mikulicic 0:c0ecb8bf28eb 11199 * for function get_tok() for rationale for that.
Marko Mikulicic 0:c0ecb8bf28eb 11200 */
Marko Mikulicic 0:c0ecb8bf28eb 11201 static const struct v7_vec_const s_keywords[] = {
Marko Mikulicic 0:c0ecb8bf28eb 11202 V7_VEC("break"), V7_VEC("case"), V7_VEC("catch"),
Marko Mikulicic 0:c0ecb8bf28eb 11203 V7_VEC("continue"), V7_VEC("debugger"), V7_VEC("default"),
Marko Mikulicic 0:c0ecb8bf28eb 11204 V7_VEC("delete"), V7_VEC("do"), V7_VEC("else"),
Marko Mikulicic 0:c0ecb8bf28eb 11205 V7_VEC("false"), V7_VEC("finally"), V7_VEC("for"),
Marko Mikulicic 0:c0ecb8bf28eb 11206 V7_VEC("function"), V7_VEC("if"), V7_VEC("in"),
Marko Mikulicic 0:c0ecb8bf28eb 11207 V7_VEC("instanceof"), V7_VEC("new"), V7_VEC("null"),
Marko Mikulicic 0:c0ecb8bf28eb 11208 V7_VEC("return"), V7_VEC("switch"), V7_VEC("this"),
Marko Mikulicic 0:c0ecb8bf28eb 11209 V7_VEC("throw"), V7_VEC("true"), V7_VEC("try"),
Marko Mikulicic 0:c0ecb8bf28eb 11210 V7_VEC("typeof"), V7_VEC("var"), V7_VEC("void"),
Marko Mikulicic 0:c0ecb8bf28eb 11211 V7_VEC("while"), V7_VEC("with")};
Marko Mikulicic 0:c0ecb8bf28eb 11212
Marko Mikulicic 0:c0ecb8bf28eb 11213 V7_PRIVATE int is_reserved_word_token(enum v7_tok tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11214 return tok >= TOK_BREAK && tok <= TOK_WITH;
Marko Mikulicic 0:c0ecb8bf28eb 11215 }
Marko Mikulicic 0:c0ecb8bf28eb 11216
Marko Mikulicic 0:c0ecb8bf28eb 11217 /*
Marko Mikulicic 0:c0ecb8bf28eb 11218 * Move ptr to the next token, skipping comments and whitespaces.
Marko Mikulicic 0:c0ecb8bf28eb 11219 * Return number of new line characters detected.
Marko Mikulicic 0:c0ecb8bf28eb 11220 */
Marko Mikulicic 0:c0ecb8bf28eb 11221 V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11222 const char *s = *ptr, *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11223 int num_lines = 0;
Marko Mikulicic 0:c0ecb8bf28eb 11224
Marko Mikulicic 0:c0ecb8bf28eb 11225 while (s != p && s < src_end && *s != '\0' &&
Marko Mikulicic 0:c0ecb8bf28eb 11226 (isspace((unsigned char) *s) || *s == '/')) {
Marko Mikulicic 0:c0ecb8bf28eb 11227 p = s;
Marko Mikulicic 0:c0ecb8bf28eb 11228 while (s < src_end && *s != '\0' && isspace((unsigned char) *s)) {
Marko Mikulicic 0:c0ecb8bf28eb 11229 if (*s == '\n') num_lines++;
Marko Mikulicic 0:c0ecb8bf28eb 11230 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11231 }
Marko Mikulicic 0:c0ecb8bf28eb 11232 if ((s + 1) < src_end && s[0] == '/' && s[1] == '/') {
Marko Mikulicic 0:c0ecb8bf28eb 11233 s += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11234 while (s < src_end && s[0] != '\0' && s[0] != '\n') s++;
Marko Mikulicic 0:c0ecb8bf28eb 11235 }
Marko Mikulicic 0:c0ecb8bf28eb 11236 if ((s + 1) < src_end && s[0] == '/' && s[1] == '*') {
Marko Mikulicic 0:c0ecb8bf28eb 11237 s += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11238 while (s < src_end && s[0] != '\0' && !(s[-1] == '/' && s[-2] == '*')) {
Marko Mikulicic 0:c0ecb8bf28eb 11239 if (s[0] == '\n') num_lines++;
Marko Mikulicic 0:c0ecb8bf28eb 11240 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11241 }
Marko Mikulicic 0:c0ecb8bf28eb 11242 }
Marko Mikulicic 0:c0ecb8bf28eb 11243 }
Marko Mikulicic 0:c0ecb8bf28eb 11244 *ptr = s;
Marko Mikulicic 0:c0ecb8bf28eb 11245
Marko Mikulicic 0:c0ecb8bf28eb 11246 return num_lines;
Marko Mikulicic 0:c0ecb8bf28eb 11247 }
Marko Mikulicic 0:c0ecb8bf28eb 11248
Marko Mikulicic 0:c0ecb8bf28eb 11249 /* Advance `s` pointer to the end of identifier */
Marko Mikulicic 0:c0ecb8bf28eb 11250 static void ident(const char **s, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11251 const unsigned char *p = (unsigned char *) *s;
Marko Mikulicic 0:c0ecb8bf28eb 11252 int n;
Marko Mikulicic 0:c0ecb8bf28eb 11253 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 11254
Marko Mikulicic 0:c0ecb8bf28eb 11255 while ((const char *) p < src_end && p[0] != '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 11256 if (p[0] == '$' || p[0] == '_' || isalnum(p[0])) {
Marko Mikulicic 0:c0ecb8bf28eb 11257 /* $, _, or any alphanumeric are valid identifier characters */
Marko Mikulicic 0:c0ecb8bf28eb 11258 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11259 } else if ((const char *) (p + 5) < src_end && p[0] == '\\' &&
Marko Mikulicic 0:c0ecb8bf28eb 11260 p[1] == 'u' && isxdigit(p[2]) && isxdigit(p[3]) &&
Marko Mikulicic 0:c0ecb8bf28eb 11261 isxdigit(p[4]) && isxdigit(p[5])) {
Marko Mikulicic 0:c0ecb8bf28eb 11262 /* Unicode escape, \uXXXX . Could be used like "var \u0078 = 1;" */
Marko Mikulicic 0:c0ecb8bf28eb 11263 p += 6;
Marko Mikulicic 0:c0ecb8bf28eb 11264 } else if ((n = chartorune(&r, (char *) p)) > 1 && isalpharune(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 11265 /*
Marko Mikulicic 0:c0ecb8bf28eb 11266 * TODO(dfrank): the chartorune() call above can read `p` past the
Marko Mikulicic 0:c0ecb8bf28eb 11267 * src_end, so it might crash on incorrect code. The solution would be
Marko Mikulicic 0:c0ecb8bf28eb 11268 * to modify `chartorune()` to accept src_end argument as well.
Marko Mikulicic 0:c0ecb8bf28eb 11269 */
Marko Mikulicic 0:c0ecb8bf28eb 11270 /* Unicode alphanumeric character */
Marko Mikulicic 0:c0ecb8bf28eb 11271 p += n;
Marko Mikulicic 0:c0ecb8bf28eb 11272 } else {
Marko Mikulicic 0:c0ecb8bf28eb 11273 break;
Marko Mikulicic 0:c0ecb8bf28eb 11274 }
Marko Mikulicic 0:c0ecb8bf28eb 11275 }
Marko Mikulicic 0:c0ecb8bf28eb 11276
Marko Mikulicic 0:c0ecb8bf28eb 11277 *s = (char *) p;
Marko Mikulicic 0:c0ecb8bf28eb 11278 }
Marko Mikulicic 0:c0ecb8bf28eb 11279
Marko Mikulicic 0:c0ecb8bf28eb 11280 static enum v7_tok kw(const char *s, size_t len, int ntoks, enum v7_tok tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11281 int i;
Marko Mikulicic 0:c0ecb8bf28eb 11282
Marko Mikulicic 0:c0ecb8bf28eb 11283 for (i = 0; i < ntoks; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 11284 if (s_keywords[(tok - TOK_BREAK) + i].len == len &&
Marko Mikulicic 0:c0ecb8bf28eb 11285 memcmp(s_keywords[(tok - TOK_BREAK) + i].p + 1, s + 1, len - 1) == 0)
Marko Mikulicic 0:c0ecb8bf28eb 11286 break;
Marko Mikulicic 0:c0ecb8bf28eb 11287 }
Marko Mikulicic 0:c0ecb8bf28eb 11288
Marko Mikulicic 0:c0ecb8bf28eb 11289 return i == ntoks ? TOK_IDENTIFIER : (enum v7_tok)(tok + i);
Marko Mikulicic 0:c0ecb8bf28eb 11290 }
Marko Mikulicic 0:c0ecb8bf28eb 11291
Marko Mikulicic 0:c0ecb8bf28eb 11292 static enum v7_tok punct1(const char **s, const char *src_end, int ch1,
Marko Mikulicic 0:c0ecb8bf28eb 11293 enum v7_tok tok1, enum v7_tok tok2) {
Marko Mikulicic 0:c0ecb8bf28eb 11294 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11295 if (*s < src_end && **s == ch1) {
Marko Mikulicic 0:c0ecb8bf28eb 11296 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11297 return tok1;
Marko Mikulicic 0:c0ecb8bf28eb 11298 } else {
Marko Mikulicic 0:c0ecb8bf28eb 11299 return tok2;
Marko Mikulicic 0:c0ecb8bf28eb 11300 }
Marko Mikulicic 0:c0ecb8bf28eb 11301 }
Marko Mikulicic 0:c0ecb8bf28eb 11302
Marko Mikulicic 0:c0ecb8bf28eb 11303 static enum v7_tok punct2(const char **s, const char *src_end, int ch1,
Marko Mikulicic 0:c0ecb8bf28eb 11304 enum v7_tok tok1, int ch2, enum v7_tok tok2,
Marko Mikulicic 0:c0ecb8bf28eb 11305 enum v7_tok tok3) {
Marko Mikulicic 0:c0ecb8bf28eb 11306 if ((*s + 2) < src_end && s[0][1] == ch1 && s[0][2] == ch2) {
Marko Mikulicic 0:c0ecb8bf28eb 11307 (*s) += 3;
Marko Mikulicic 0:c0ecb8bf28eb 11308 return tok2;
Marko Mikulicic 0:c0ecb8bf28eb 11309 }
Marko Mikulicic 0:c0ecb8bf28eb 11310
Marko Mikulicic 0:c0ecb8bf28eb 11311 return punct1(s, src_end, ch1, tok1, tok3);
Marko Mikulicic 0:c0ecb8bf28eb 11312 }
Marko Mikulicic 0:c0ecb8bf28eb 11313
Marko Mikulicic 0:c0ecb8bf28eb 11314 static enum v7_tok punct3(const char **s, const char *src_end, int ch1,
Marko Mikulicic 0:c0ecb8bf28eb 11315 enum v7_tok tok1, int ch2, enum v7_tok tok2,
Marko Mikulicic 0:c0ecb8bf28eb 11316 enum v7_tok tok3) {
Marko Mikulicic 0:c0ecb8bf28eb 11317 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11318 if (*s < src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11319 if (**s == ch1) {
Marko Mikulicic 0:c0ecb8bf28eb 11320 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11321 return tok1;
Marko Mikulicic 0:c0ecb8bf28eb 11322 } else if (**s == ch2) {
Marko Mikulicic 0:c0ecb8bf28eb 11323 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11324 return tok2;
Marko Mikulicic 0:c0ecb8bf28eb 11325 }
Marko Mikulicic 0:c0ecb8bf28eb 11326 }
Marko Mikulicic 0:c0ecb8bf28eb 11327 return tok3;
Marko Mikulicic 0:c0ecb8bf28eb 11328 }
Marko Mikulicic 0:c0ecb8bf28eb 11329
Marko Mikulicic 0:c0ecb8bf28eb 11330 static void parse_number(const char *s, const char **end, double *num) {
Marko Mikulicic 0:c0ecb8bf28eb 11331 *num = cs_strtod(s, (char **) end);
Marko Mikulicic 0:c0ecb8bf28eb 11332 }
Marko Mikulicic 0:c0ecb8bf28eb 11333
Marko Mikulicic 0:c0ecb8bf28eb 11334 static enum v7_tok parse_str_literal(const char **p, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11335 const char *s = *p;
Marko Mikulicic 0:c0ecb8bf28eb 11336 int quote = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 11337
Marko Mikulicic 0:c0ecb8bf28eb 11338 if (s < src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11339 quote = *s++;
Marko Mikulicic 0:c0ecb8bf28eb 11340 }
Marko Mikulicic 0:c0ecb8bf28eb 11341
Marko Mikulicic 0:c0ecb8bf28eb 11342 /* Scan string literal, handle escape sequences */
Marko Mikulicic 0:c0ecb8bf28eb 11343 for (; s < src_end && *s != '\0' && *s != quote; s++) {
Marko Mikulicic 0:c0ecb8bf28eb 11344 if (*s == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 11345 switch (s[1]) {
Marko Mikulicic 0:c0ecb8bf28eb 11346 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 11347 case 'f':
Marko Mikulicic 0:c0ecb8bf28eb 11348 case 'n':
Marko Mikulicic 0:c0ecb8bf28eb 11349 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 11350 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 11351 case 'v':
Marko Mikulicic 0:c0ecb8bf28eb 11352 case '\\':
Marko Mikulicic 0:c0ecb8bf28eb 11353 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11354 break;
Marko Mikulicic 0:c0ecb8bf28eb 11355 default:
Marko Mikulicic 0:c0ecb8bf28eb 11356 if (s[1] == quote) s++;
Marko Mikulicic 0:c0ecb8bf28eb 11357 break;
Marko Mikulicic 0:c0ecb8bf28eb 11358 }
Marko Mikulicic 0:c0ecb8bf28eb 11359 }
Marko Mikulicic 0:c0ecb8bf28eb 11360 }
Marko Mikulicic 0:c0ecb8bf28eb 11361
Marko Mikulicic 0:c0ecb8bf28eb 11362 if (s < src_end && *s == quote) {
Marko Mikulicic 0:c0ecb8bf28eb 11363 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11364 *p = s;
Marko Mikulicic 0:c0ecb8bf28eb 11365 return TOK_STRING_LITERAL;
Marko Mikulicic 0:c0ecb8bf28eb 11366 } else {
Marko Mikulicic 0:c0ecb8bf28eb 11367 return TOK_END_OF_INPUT;
Marko Mikulicic 0:c0ecb8bf28eb 11368 }
Marko Mikulicic 0:c0ecb8bf28eb 11369 }
Marko Mikulicic 0:c0ecb8bf28eb 11370
Marko Mikulicic 0:c0ecb8bf28eb 11371 /*
Marko Mikulicic 0:c0ecb8bf28eb 11372 * This function is the heart of the tokenizer.
Marko Mikulicic 0:c0ecb8bf28eb 11373 * Organized as a giant switch statement.
Marko Mikulicic 0:c0ecb8bf28eb 11374 *
Marko Mikulicic 0:c0ecb8bf28eb 11375 * Switch statement is by the first character of the input stream. If first
Marko Mikulicic 0:c0ecb8bf28eb 11376 * character begins with a letter, it could be either keyword or identifier.
Marko Mikulicic 0:c0ecb8bf28eb 11377 * get_tok() calls ident() which shifts `s` pointer to the end of the word.
Marko Mikulicic 0:c0ecb8bf28eb 11378 * Now, tokenizer knows that the word begins at `p` and ends at `s`.
Marko Mikulicic 0:c0ecb8bf28eb 11379 * It calls function kw() to scan over the keywords that start with `p[0]`
Marko Mikulicic 0:c0ecb8bf28eb 11380 * letter. Therefore, keyword tokens and keyword strings must be in the
Marko Mikulicic 0:c0ecb8bf28eb 11381 * same order, to let kw() function work properly.
Marko Mikulicic 0:c0ecb8bf28eb 11382 * If kw() finds a keyword match, it returns keyword token.
Marko Mikulicic 0:c0ecb8bf28eb 11383 * Otherwise, it returns TOK_IDENTIFIER.
Marko Mikulicic 0:c0ecb8bf28eb 11384 * NOTE(lsm): `prev_tok` is a previously parsed token. It is needed for
Marko Mikulicic 0:c0ecb8bf28eb 11385 * correctly parsing regex literals.
Marko Mikulicic 0:c0ecb8bf28eb 11386 */
Marko Mikulicic 0:c0ecb8bf28eb 11387 V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n,
Marko Mikulicic 0:c0ecb8bf28eb 11388 enum v7_tok prev_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11389 const char *p = *s;
Marko Mikulicic 0:c0ecb8bf28eb 11390
Marko Mikulicic 0:c0ecb8bf28eb 11391 if (p >= src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11392 return TOK_END_OF_INPUT;
Marko Mikulicic 0:c0ecb8bf28eb 11393 }
Marko Mikulicic 0:c0ecb8bf28eb 11394
Marko Mikulicic 0:c0ecb8bf28eb 11395 switch (*p) {
Marko Mikulicic 0:c0ecb8bf28eb 11396 /* Letters */
Marko Mikulicic 0:c0ecb8bf28eb 11397 case 'a':
Marko Mikulicic 0:c0ecb8bf28eb 11398 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11399 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11400 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 11401 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11402 return kw(p, *s - p, 1, TOK_BREAK);
Marko Mikulicic 0:c0ecb8bf28eb 11403 case 'c':
Marko Mikulicic 0:c0ecb8bf28eb 11404 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11405 return kw(p, *s - p, 3, TOK_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 11406 case 'd':
Marko Mikulicic 0:c0ecb8bf28eb 11407 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11408 return kw(p, *s - p, 4, TOK_DEBUGGER);
Marko Mikulicic 0:c0ecb8bf28eb 11409 case 'e':
Marko Mikulicic 0:c0ecb8bf28eb 11410 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11411 return kw(p, *s - p, 1, TOK_ELSE);
Marko Mikulicic 0:c0ecb8bf28eb 11412 case 'f':
Marko Mikulicic 0:c0ecb8bf28eb 11413 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11414 return kw(p, *s - p, 4, TOK_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 11415 case 'g':
Marko Mikulicic 0:c0ecb8bf28eb 11416 case 'h':
Marko Mikulicic 0:c0ecb8bf28eb 11417 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11418 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11419 case 'i':
Marko Mikulicic 0:c0ecb8bf28eb 11420 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11421 return kw(p, *s - p, 3, TOK_IF);
Marko Mikulicic 0:c0ecb8bf28eb 11422 case 'j':
Marko Mikulicic 0:c0ecb8bf28eb 11423 case 'k':
Marko Mikulicic 0:c0ecb8bf28eb 11424 case 'l':
Marko Mikulicic 0:c0ecb8bf28eb 11425 case 'm':
Marko Mikulicic 0:c0ecb8bf28eb 11426 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11427 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11428 case 'n':
Marko Mikulicic 0:c0ecb8bf28eb 11429 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11430 return kw(p, *s - p, 2, TOK_NEW);
Marko Mikulicic 0:c0ecb8bf28eb 11431 case 'o':
Marko Mikulicic 0:c0ecb8bf28eb 11432 case 'p':
Marko Mikulicic 0:c0ecb8bf28eb 11433 case 'q':
Marko Mikulicic 0:c0ecb8bf28eb 11434 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11435 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11436 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 11437 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11438 return kw(p, *s - p, 1, TOK_RETURN);
Marko Mikulicic 0:c0ecb8bf28eb 11439 case 's':
Marko Mikulicic 0:c0ecb8bf28eb 11440 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11441 return kw(p, *s - p, 1, TOK_SWITCH);
Marko Mikulicic 0:c0ecb8bf28eb 11442 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 11443 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11444 return kw(p, *s - p, 5, TOK_THIS);
Marko Mikulicic 0:c0ecb8bf28eb 11445 case 'u':
Marko Mikulicic 0:c0ecb8bf28eb 11446 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11447 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11448 case 'v':
Marko Mikulicic 0:c0ecb8bf28eb 11449 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11450 return kw(p, *s - p, 2, TOK_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 11451 case 'w':
Marko Mikulicic 0:c0ecb8bf28eb 11452 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11453 return kw(p, *s - p, 2, TOK_WHILE);
Marko Mikulicic 0:c0ecb8bf28eb 11454 case 'x':
Marko Mikulicic 0:c0ecb8bf28eb 11455 case 'y':
Marko Mikulicic 0:c0ecb8bf28eb 11456 case 'z':
Marko Mikulicic 0:c0ecb8bf28eb 11457 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11458 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11459
Marko Mikulicic 0:c0ecb8bf28eb 11460 case '_':
Marko Mikulicic 0:c0ecb8bf28eb 11461 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 11462 case 'A':
Marko Mikulicic 0:c0ecb8bf28eb 11463 case 'B':
Marko Mikulicic 0:c0ecb8bf28eb 11464 case 'C':
Marko Mikulicic 0:c0ecb8bf28eb 11465 case 'D':
Marko Mikulicic 0:c0ecb8bf28eb 11466 case 'E':
Marko Mikulicic 0:c0ecb8bf28eb 11467 case 'F':
Marko Mikulicic 0:c0ecb8bf28eb 11468 case 'G':
Marko Mikulicic 0:c0ecb8bf28eb 11469 case 'H':
Marko Mikulicic 0:c0ecb8bf28eb 11470 case 'I':
Marko Mikulicic 0:c0ecb8bf28eb 11471 case 'J':
Marko Mikulicic 0:c0ecb8bf28eb 11472 case 'K':
Marko Mikulicic 0:c0ecb8bf28eb 11473 case 'L':
Marko Mikulicic 0:c0ecb8bf28eb 11474 case 'M':
Marko Mikulicic 0:c0ecb8bf28eb 11475 case 'N':
Marko Mikulicic 0:c0ecb8bf28eb 11476 case 'O':
Marko Mikulicic 0:c0ecb8bf28eb 11477 case 'P':
Marko Mikulicic 0:c0ecb8bf28eb 11478 case 'Q':
Marko Mikulicic 0:c0ecb8bf28eb 11479 case 'R':
Marko Mikulicic 0:c0ecb8bf28eb 11480 case 'S':
Marko Mikulicic 0:c0ecb8bf28eb 11481 case 'T':
Marko Mikulicic 0:c0ecb8bf28eb 11482 case 'U':
Marko Mikulicic 0:c0ecb8bf28eb 11483 case 'V':
Marko Mikulicic 0:c0ecb8bf28eb 11484 case 'W':
Marko Mikulicic 0:c0ecb8bf28eb 11485 case 'X':
Marko Mikulicic 0:c0ecb8bf28eb 11486 case 'Y':
Marko Mikulicic 0:c0ecb8bf28eb 11487 case 'Z':
Marko Mikulicic 0:c0ecb8bf28eb 11488 case '\\': /* Identifier may start with unicode escape sequence */
Marko Mikulicic 0:c0ecb8bf28eb 11489 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11490 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11491
Marko Mikulicic 0:c0ecb8bf28eb 11492 /* Numbers */
Marko Mikulicic 0:c0ecb8bf28eb 11493 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 11494 case '1':
Marko Mikulicic 0:c0ecb8bf28eb 11495 case '2':
Marko Mikulicic 0:c0ecb8bf28eb 11496 case '3':
Marko Mikulicic 0:c0ecb8bf28eb 11497 case '4':
Marko Mikulicic 0:c0ecb8bf28eb 11498 case '5':
Marko Mikulicic 0:c0ecb8bf28eb 11499 case '6':
Marko Mikulicic 0:c0ecb8bf28eb 11500 case '7':
Marko Mikulicic 0:c0ecb8bf28eb 11501 case '8':
Marko Mikulicic 0:c0ecb8bf28eb 11502 case '9':
Marko Mikulicic 0:c0ecb8bf28eb 11503 parse_number(p, s, n);
Marko Mikulicic 0:c0ecb8bf28eb 11504 return TOK_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 11505
Marko Mikulicic 0:c0ecb8bf28eb 11506 /* String literals */
Marko Mikulicic 0:c0ecb8bf28eb 11507 case '\'':
Marko Mikulicic 0:c0ecb8bf28eb 11508 case '"':
Marko Mikulicic 0:c0ecb8bf28eb 11509 return parse_str_literal(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11510
Marko Mikulicic 0:c0ecb8bf28eb 11511 /* Punctuators */
Marko Mikulicic 0:c0ecb8bf28eb 11512 case '=':
Marko Mikulicic 0:c0ecb8bf28eb 11513 return punct2(s, src_end, '=', TOK_EQ, '=', TOK_EQ_EQ, TOK_ASSIGN);
Marko Mikulicic 0:c0ecb8bf28eb 11514 case '!':
Marko Mikulicic 0:c0ecb8bf28eb 11515 return punct2(s, src_end, '=', TOK_NE, '=', TOK_NE_NE, TOK_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 11516
Marko Mikulicic 0:c0ecb8bf28eb 11517 case '%':
Marko Mikulicic 0:c0ecb8bf28eb 11518 return punct1(s, src_end, '=', TOK_REM_ASSIGN, TOK_REM);
Marko Mikulicic 0:c0ecb8bf28eb 11519 case '*':
Marko Mikulicic 0:c0ecb8bf28eb 11520 return punct1(s, src_end, '=', TOK_MUL_ASSIGN, TOK_MUL);
Marko Mikulicic 0:c0ecb8bf28eb 11521 case '/':
Marko Mikulicic 0:c0ecb8bf28eb 11522 /*
Marko Mikulicic 0:c0ecb8bf28eb 11523 * TOK_DIV, TOK_DIV_ASSIGN, and TOK_REGEX_LITERAL start with `/` char.
Marko Mikulicic 0:c0ecb8bf28eb 11524 * Division can happen after an expression.
Marko Mikulicic 0:c0ecb8bf28eb 11525 * In expressions like this:
Marko Mikulicic 0:c0ecb8bf28eb 11526 * a /= b; c /= d;
Marko Mikulicic 0:c0ecb8bf28eb 11527 * things between slashes is NOT a regex literal.
Marko Mikulicic 0:c0ecb8bf28eb 11528 * The switch below catches all cases where division happens.
Marko Mikulicic 0:c0ecb8bf28eb 11529 */
Marko Mikulicic 0:c0ecb8bf28eb 11530 switch (prev_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11531 case TOK_CLOSE_CURLY:
Marko Mikulicic 0:c0ecb8bf28eb 11532 case TOK_CLOSE_PAREN:
Marko Mikulicic 0:c0ecb8bf28eb 11533 case TOK_CLOSE_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 11534 case TOK_IDENTIFIER:
Marko Mikulicic 0:c0ecb8bf28eb 11535 case TOK_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 11536 return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV);
Marko Mikulicic 0:c0ecb8bf28eb 11537 default:
Marko Mikulicic 0:c0ecb8bf28eb 11538 /* Not a division - this is a regex. Scan until closing slash */
Marko Mikulicic 0:c0ecb8bf28eb 11539 for (p++; p < src_end && *p != '\0' && *p != '\n'; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 11540 if (*p == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 11541 /* Skip escape sequence */
Marko Mikulicic 0:c0ecb8bf28eb 11542 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11543 } else if (*p == '/') {
Marko Mikulicic 0:c0ecb8bf28eb 11544 /* This is a closing slash */
Marko Mikulicic 0:c0ecb8bf28eb 11545 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11546 /* Skip regex flags */
Marko Mikulicic 0:c0ecb8bf28eb 11547 while (*p == 'g' || *p == 'i' || *p == 'm') {
Marko Mikulicic 0:c0ecb8bf28eb 11548 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11549 }
Marko Mikulicic 0:c0ecb8bf28eb 11550 *s = p;
Marko Mikulicic 0:c0ecb8bf28eb 11551 return TOK_REGEX_LITERAL;
Marko Mikulicic 0:c0ecb8bf28eb 11552 }
Marko Mikulicic 0:c0ecb8bf28eb 11553 }
Marko Mikulicic 0:c0ecb8bf28eb 11554 break;
Marko Mikulicic 0:c0ecb8bf28eb 11555 }
Marko Mikulicic 0:c0ecb8bf28eb 11556 return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV);
Marko Mikulicic 0:c0ecb8bf28eb 11557 case '^':
Marko Mikulicic 0:c0ecb8bf28eb 11558 return punct1(s, src_end, '=', TOK_XOR_ASSIGN, TOK_XOR);
Marko Mikulicic 0:c0ecb8bf28eb 11559
Marko Mikulicic 0:c0ecb8bf28eb 11560 case '+':
Marko Mikulicic 0:c0ecb8bf28eb 11561 return punct3(s, src_end, '+', TOK_PLUS_PLUS, '=', TOK_PLUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11562 TOK_PLUS);
Marko Mikulicic 0:c0ecb8bf28eb 11563 case '-':
Marko Mikulicic 0:c0ecb8bf28eb 11564 return punct3(s, src_end, '-', TOK_MINUS_MINUS, '=', TOK_MINUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11565 TOK_MINUS);
Marko Mikulicic 0:c0ecb8bf28eb 11566 case '&':
Marko Mikulicic 0:c0ecb8bf28eb 11567 return punct3(s, src_end, '&', TOK_LOGICAL_AND, '=', TOK_AND_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11568 TOK_AND);
Marko Mikulicic 0:c0ecb8bf28eb 11569 case '|':
Marko Mikulicic 0:c0ecb8bf28eb 11570 return punct3(s, src_end, '|', TOK_LOGICAL_OR, '=', TOK_OR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11571 TOK_OR);
Marko Mikulicic 0:c0ecb8bf28eb 11572
Marko Mikulicic 0:c0ecb8bf28eb 11573 case '<':
Marko Mikulicic 0:c0ecb8bf28eb 11574 if (*s + 1 < src_end && s[0][1] == '=') {
Marko Mikulicic 0:c0ecb8bf28eb 11575 (*s) += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11576 return TOK_LE;
Marko Mikulicic 0:c0ecb8bf28eb 11577 }
Marko Mikulicic 0:c0ecb8bf28eb 11578 return punct2(s, src_end, '<', TOK_LSHIFT, '=', TOK_LSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11579 TOK_LT);
Marko Mikulicic 0:c0ecb8bf28eb 11580 case '>':
Marko Mikulicic 0:c0ecb8bf28eb 11581 if (*s + 1 < src_end && s[0][1] == '=') {
Marko Mikulicic 0:c0ecb8bf28eb 11582 (*s) += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11583 return TOK_GE;
Marko Mikulicic 0:c0ecb8bf28eb 11584 }
Marko Mikulicic 0:c0ecb8bf28eb 11585 if (*s + 3 < src_end && s[0][1] == '>' && s[0][2] == '>' &&
Marko Mikulicic 0:c0ecb8bf28eb 11586 s[0][3] == '=') {
Marko Mikulicic 0:c0ecb8bf28eb 11587 (*s) += 4;
Marko Mikulicic 0:c0ecb8bf28eb 11588 return TOK_URSHIFT_ASSIGN;
Marko Mikulicic 0:c0ecb8bf28eb 11589 }
Marko Mikulicic 0:c0ecb8bf28eb 11590 if (*s + 2 < src_end && s[0][1] == '>' && s[0][2] == '>') {
Marko Mikulicic 0:c0ecb8bf28eb 11591 (*s) += 3;
Marko Mikulicic 0:c0ecb8bf28eb 11592 return TOK_URSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 11593 }
Marko Mikulicic 0:c0ecb8bf28eb 11594 return punct2(s, src_end, '>', TOK_RSHIFT, '=', TOK_RSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11595 TOK_GT);
Marko Mikulicic 0:c0ecb8bf28eb 11596
Marko Mikulicic 0:c0ecb8bf28eb 11597 case '{':
Marko Mikulicic 0:c0ecb8bf28eb 11598 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11599 return TOK_OPEN_CURLY;
Marko Mikulicic 0:c0ecb8bf28eb 11600 case '}':
Marko Mikulicic 0:c0ecb8bf28eb 11601 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11602 return TOK_CLOSE_CURLY;
Marko Mikulicic 0:c0ecb8bf28eb 11603 case '(':
Marko Mikulicic 0:c0ecb8bf28eb 11604 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11605 return TOK_OPEN_PAREN;
Marko Mikulicic 0:c0ecb8bf28eb 11606 case ')':
Marko Mikulicic 0:c0ecb8bf28eb 11607 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11608 return TOK_CLOSE_PAREN;
Marko Mikulicic 0:c0ecb8bf28eb 11609 case '[':
Marko Mikulicic 0:c0ecb8bf28eb 11610 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11611 return TOK_OPEN_BRACKET;
Marko Mikulicic 0:c0ecb8bf28eb 11612 case ']':
Marko Mikulicic 0:c0ecb8bf28eb 11613 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11614 return TOK_CLOSE_BRACKET;
Marko Mikulicic 0:c0ecb8bf28eb 11615 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 11616 switch (*(*s + 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 11617 /* Numbers */
Marko Mikulicic 0:c0ecb8bf28eb 11618 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 11619 case '1':
Marko Mikulicic 0:c0ecb8bf28eb 11620 case '2':
Marko Mikulicic 0:c0ecb8bf28eb 11621 case '3':
Marko Mikulicic 0:c0ecb8bf28eb 11622 case '4':
Marko Mikulicic 0:c0ecb8bf28eb 11623 case '5':
Marko Mikulicic 0:c0ecb8bf28eb 11624 case '6':
Marko Mikulicic 0:c0ecb8bf28eb 11625 case '7':
Marko Mikulicic 0:c0ecb8bf28eb 11626 case '8':
Marko Mikulicic 0:c0ecb8bf28eb 11627 case '9':
Marko Mikulicic 0:c0ecb8bf28eb 11628 parse_number(p, s, n);
Marko Mikulicic 0:c0ecb8bf28eb 11629 return TOK_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 11630 }
Marko Mikulicic 0:c0ecb8bf28eb 11631 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11632 return TOK_DOT;
Marko Mikulicic 0:c0ecb8bf28eb 11633 case ';':
Marko Mikulicic 0:c0ecb8bf28eb 11634 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11635 return TOK_SEMICOLON;
Marko Mikulicic 0:c0ecb8bf28eb 11636 case ':':
Marko Mikulicic 0:c0ecb8bf28eb 11637 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11638 return TOK_COLON;
Marko Mikulicic 0:c0ecb8bf28eb 11639 case '?':
Marko Mikulicic 0:c0ecb8bf28eb 11640 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11641 return TOK_QUESTION;
Marko Mikulicic 0:c0ecb8bf28eb 11642 case '~':
Marko Mikulicic 0:c0ecb8bf28eb 11643 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11644 return TOK_TILDA;
Marko Mikulicic 0:c0ecb8bf28eb 11645 case ',':
Marko Mikulicic 0:c0ecb8bf28eb 11646 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11647 return TOK_COMMA;
Marko Mikulicic 0:c0ecb8bf28eb 11648
Marko Mikulicic 0:c0ecb8bf28eb 11649 default: {
Marko Mikulicic 0:c0ecb8bf28eb 11650 /* Handle unicode variables */
Marko Mikulicic 0:c0ecb8bf28eb 11651 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 11652 if (chartorune(&r, *s) > 1 && isalpharune(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 11653 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11654 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11655 }
Marko Mikulicic 0:c0ecb8bf28eb 11656 return TOK_END_OF_INPUT;
Marko Mikulicic 0:c0ecb8bf28eb 11657 }
Marko Mikulicic 0:c0ecb8bf28eb 11658 }
Marko Mikulicic 0:c0ecb8bf28eb 11659 }
Marko Mikulicic 0:c0ecb8bf28eb 11660
Marko Mikulicic 0:c0ecb8bf28eb 11661 #ifdef TEST_RUN
Marko Mikulicic 0:c0ecb8bf28eb 11662 int main(void) {
Marko Mikulicic 0:c0ecb8bf28eb 11663 const char *src =
Marko Mikulicic 0:c0ecb8bf28eb 11664 "for (var fo++ = -1; /= <= 1.17; x<<) { == <<=, 'x')} "
Marko Mikulicic 0:c0ecb8bf28eb 11665 "Infinity %=x<<=2";
Marko Mikulicic 0:c0ecb8bf28eb 11666 const char *src_end = src + strlen(src);
Marko Mikulicic 0:c0ecb8bf28eb 11667 enum v7_tok tok;
Marko Mikulicic 0:c0ecb8bf28eb 11668 double num;
Marko Mikulicic 0:c0ecb8bf28eb 11669 const char *p = src;
Marko Mikulicic 0:c0ecb8bf28eb 11670
Marko Mikulicic 0:c0ecb8bf28eb 11671 skip_to_next_tok(&src, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11672 while ((tok = get_tok(&src, src_end, &num)) != TOK_END_OF_INPUT) {
Marko Mikulicic 0:c0ecb8bf28eb 11673 printf("%d [%.*s]\n", tok, (int) (src - p), p);
Marko Mikulicic 0:c0ecb8bf28eb 11674 skip_to_next_tok(&src, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11675 p = src;
Marko Mikulicic 0:c0ecb8bf28eb 11676 }
Marko Mikulicic 0:c0ecb8bf28eb 11677 printf("%d [%.*s]\n", tok, (int) (src - p), p);
Marko Mikulicic 0:c0ecb8bf28eb 11678
Marko Mikulicic 0:c0ecb8bf28eb 11679 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 11680 }
Marko Mikulicic 0:c0ecb8bf28eb 11681 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11682
Marko Mikulicic 0:c0ecb8bf28eb 11683 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 11684 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 11685 #line 1 "v7/src/ast.c"
Marko Mikulicic 0:c0ecb8bf28eb 11686 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11687 /*
Marko Mikulicic 0:c0ecb8bf28eb 11688 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 11689 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 11690 */
Marko Mikulicic 0:c0ecb8bf28eb 11691
Marko Mikulicic 0:c0ecb8bf28eb 11692 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11693 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11694
Marko Mikulicic 0:c0ecb8bf28eb 11695 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11696 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11697 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11698 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11699 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11700 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11701
Marko Mikulicic 0:c0ecb8bf28eb 11702 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 11703
Marko Mikulicic 0:c0ecb8bf28eb 11704 #ifdef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 11705 typedef uint32_t ast_skip_t;
Marko Mikulicic 0:c0ecb8bf28eb 11706 #else
Marko Mikulicic 0:c0ecb8bf28eb 11707 typedef uint16_t ast_skip_t;
Marko Mikulicic 0:c0ecb8bf28eb 11708 #define AST_SKIP_MAX UINT16_MAX
Marko Mikulicic 0:c0ecb8bf28eb 11709 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11710
Marko Mikulicic 0:c0ecb8bf28eb 11711 #ifndef V7_DISABLE_AST_TAG_NAMES
Marko Mikulicic 0:c0ecb8bf28eb 11712 #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \
Marko Mikulicic 0:c0ecb8bf28eb 11713 { (name), (has_varint), (has_inlined), (num_skips), (num_subtrees) }
Marko Mikulicic 0:c0ecb8bf28eb 11714 #else
Marko Mikulicic 0:c0ecb8bf28eb 11715 #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \
Marko Mikulicic 0:c0ecb8bf28eb 11716 { (has_varint), (has_inlined), (num_skips), (num_subtrees) }
Marko Mikulicic 0:c0ecb8bf28eb 11717 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11718
Marko Mikulicic 0:c0ecb8bf28eb 11719 /*
Marko Mikulicic 0:c0ecb8bf28eb 11720 * The structure of AST nodes cannot be described in portable ANSI C,
Marko Mikulicic 0:c0ecb8bf28eb 11721 * since they are variable length and packed (unaligned).
Marko Mikulicic 0:c0ecb8bf28eb 11722 *
Marko Mikulicic 0:c0ecb8bf28eb 11723 * Here each node's body is described with a pseudo-C structure notation.
Marko Mikulicic 0:c0ecb8bf28eb 11724 * The pseudo type `child` represents a variable length byte sequence
Marko Mikulicic 0:c0ecb8bf28eb 11725 * representing a fully serialized child node.
Marko Mikulicic 0:c0ecb8bf28eb 11726 *
Marko Mikulicic 0:c0ecb8bf28eb 11727 * `child body[]` represents a sequence of such subtrees.
Marko Mikulicic 0:c0ecb8bf28eb 11728 *
Marko Mikulicic 0:c0ecb8bf28eb 11729 * Pseudo-labels, such as `end:` represent the targets of skip fields
Marko Mikulicic 0:c0ecb8bf28eb 11730 * with the same name (e.g. `ast_skip_t end`).
Marko Mikulicic 0:c0ecb8bf28eb 11731 *
Marko Mikulicic 0:c0ecb8bf28eb 11732 * Skips allow skipping a subtree or sequence of subtrees.
Marko Mikulicic 0:c0ecb8bf28eb 11733 *
Marko Mikulicic 0:c0ecb8bf28eb 11734 * Sequences of subtrees (i.e. `child []`) have to be terminated by a skip:
Marko Mikulicic 0:c0ecb8bf28eb 11735 * they don't have a termination tag; all nodes whose position is before the
Marko Mikulicic 0:c0ecb8bf28eb 11736 * skip are part of the sequence.
Marko Mikulicic 0:c0ecb8bf28eb 11737 *
Marko Mikulicic 0:c0ecb8bf28eb 11738 * Skips are encoded as network-byte-order 16-bit offsets counted from the
Marko Mikulicic 0:c0ecb8bf28eb 11739 * first byte of the node body (i.e. not counting the tag itself).
Marko Mikulicic 0:c0ecb8bf28eb 11740 * This currently limits the the maximum size of a function body to 64k.
Marko Mikulicic 0:c0ecb8bf28eb 11741 *
Marko Mikulicic 0:c0ecb8bf28eb 11742 * Notes:
Marko Mikulicic 0:c0ecb8bf28eb 11743 *
Marko Mikulicic 0:c0ecb8bf28eb 11744 * - Some nodes contain skips just for performance or because it simplifies
Marko Mikulicic 0:c0ecb8bf28eb 11745 * the implementation of the interpreter. For example, technically, the FOR
Marko Mikulicic 0:c0ecb8bf28eb 11746 * node doesn't need the `body` skip in order to be correctly traversed.
Marko Mikulicic 0:c0ecb8bf28eb 11747 * However, being able to quickly skip the `iter` expression is useful
Marko Mikulicic 0:c0ecb8bf28eb 11748 * also because it allows the interpreter to avoid traversing the expression
Marko Mikulicic 0:c0ecb8bf28eb 11749 * subtree without evaluating it, just in order to find the next subtree.
Marko Mikulicic 0:c0ecb8bf28eb 11750 *
Marko Mikulicic 0:c0ecb8bf28eb 11751 * - The name `skip` was chosen because `offset` was too overloaded in general
Marko Mikulicic 0:c0ecb8bf28eb 11752 * and label` is part of our domain model (i.e. JS has a label AST node type).
Marko Mikulicic 0:c0ecb8bf28eb 11753 *
Marko Mikulicic 0:c0ecb8bf28eb 11754 *
Marko Mikulicic 0:c0ecb8bf28eb 11755 * So, each node has a mandatory field: *tag* (see `enum ast_tag`), and a
Marko Mikulicic 0:c0ecb8bf28eb 11756 * number of optional fields. Whether the node has one or another optional
Marko Mikulicic 0:c0ecb8bf28eb 11757 * field is determined by the *node descriptor*: `struct ast_node_def`. For
Marko Mikulicic 0:c0ecb8bf28eb 11758 * each node type (i.e. for each element of `enum ast_tag`) there is a
Marko Mikulicic 0:c0ecb8bf28eb 11759 * corresponding descriptor: see `ast_node_defs`.
Marko Mikulicic 0:c0ecb8bf28eb 11760 *
Marko Mikulicic 0:c0ecb8bf28eb 11761 * Optional fields are:
Marko Mikulicic 0:c0ecb8bf28eb 11762 *
Marko Mikulicic 0:c0ecb8bf28eb 11763 * - *varint*: a varint-encoded number. At the moment, this field is only used
Marko Mikulicic 0:c0ecb8bf28eb 11764 * together with the next field: inlined data, and a varint number determines
Marko Mikulicic 0:c0ecb8bf28eb 11765 * the inlined data length.
Marko Mikulicic 0:c0ecb8bf28eb 11766 * - *inlined data*: a node-specific data. Size of it is determined by the
Marko Mikulicic 0:c0ecb8bf28eb 11767 * previous field: varint.
Marko Mikulicic 0:c0ecb8bf28eb 11768 * - *skips*: as explained above, these are integer offsets, encoded in
Marko Mikulicic 0:c0ecb8bf28eb 11769 * big-endian. The number of skips is determined by the node descriptor
Marko Mikulicic 0:c0ecb8bf28eb 11770 * (`struct ast_node_def`). The size of each skip is either 16 or 32 bits,
Marko Mikulicic 0:c0ecb8bf28eb 11771 * depending on whether the macro `V7_LARGE_AST` is set. The order of skips
Marko Mikulicic 0:c0ecb8bf28eb 11772 * is determined by the `enum ast_which_skip`. See examples below for
Marko Mikulicic 0:c0ecb8bf28eb 11773 * clarity.
Marko Mikulicic 0:c0ecb8bf28eb 11774 * - *subtrees*: child nodes. Some nodes have fixed number of child nodes; in
Marko Mikulicic 0:c0ecb8bf28eb 11775 * this case, the descriptor has non-zero field `num_subtrees`. Otherwise,
Marko Mikulicic 0:c0ecb8bf28eb 11776 * `num_subtrees` is zero, and consumer handles child nodes one by one, until
Marko Mikulicic 0:c0ecb8bf28eb 11777 * the end of the node is reached (end of the node is determined by the `end`
Marko Mikulicic 0:c0ecb8bf28eb 11778 * skip)
Marko Mikulicic 0:c0ecb8bf28eb 11779 *
Marko Mikulicic 0:c0ecb8bf28eb 11780 *
Marko Mikulicic 0:c0ecb8bf28eb 11781 * Examples:
Marko Mikulicic 0:c0ecb8bf28eb 11782 *
Marko Mikulicic 0:c0ecb8bf28eb 11783 * Let's start from the very easy example script: "300;"
Marko Mikulicic 0:c0ecb8bf28eb 11784 *
Marko Mikulicic 0:c0ecb8bf28eb 11785 * Tree looks as follows:
Marko Mikulicic 0:c0ecb8bf28eb 11786 *
Marko Mikulicic 0:c0ecb8bf28eb 11787 * $ ./v7 -e "300;" -t
Marko Mikulicic 0:c0ecb8bf28eb 11788 * SCRIPT
Marko Mikulicic 0:c0ecb8bf28eb 11789 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11790 * NUM 300
Marko Mikulicic 0:c0ecb8bf28eb 11791 *
Marko Mikulicic 0:c0ecb8bf28eb 11792 * Binary data is:
Marko Mikulicic 0:c0ecb8bf28eb 11793 *
Marko Mikulicic 0:c0ecb8bf28eb 11794 * $ ./v7 -e "300;" -b | od -A n -t x1
Marko Mikulicic 0:c0ecb8bf28eb 11795 * 56 07 41 53 54 56 31 30 00 01 00 09 00 00 13 03
Marko Mikulicic 0:c0ecb8bf28eb 11796 * 33 30 30
Marko Mikulicic 0:c0ecb8bf28eb 11797 *
Marko Mikulicic 0:c0ecb8bf28eb 11798 * Let's break it down and examine:
Marko Mikulicic 0:c0ecb8bf28eb 11799 *
Marko Mikulicic 0:c0ecb8bf28eb 11800 * - 56 07 41 53 54 56 31 30 00
Marko Mikulicic 0:c0ecb8bf28eb 11801 * Just a format prefix:
Marko Mikulicic 0:c0ecb8bf28eb 11802 * Null-terminated string: `"V\007ASTV10"` (see `BIN_AST_SIGNATURE`)
Marko Mikulicic 0:c0ecb8bf28eb 11803 * - 01
Marko Mikulicic 0:c0ecb8bf28eb 11804 * AST tag: `AST_SCRIPT`. As you see in `ast_node_defs` below, node of
Marko Mikulicic 0:c0ecb8bf28eb 11805 * this type has neither *varint* nor *inlined data* fields, but it has
Marko Mikulicic 0:c0ecb8bf28eb 11806 * 2 skips: `end` and `next`. `end` is a skip to the end of the current
Marko Mikulicic 0:c0ecb8bf28eb 11807 * node (`SCRIPT`), and `next` will be explained below.
Marko Mikulicic 0:c0ecb8bf28eb 11808 *
Marko Mikulicic 0:c0ecb8bf28eb 11809 * The size of each skip depends on whether `V7_LARGE_AST` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 11810 * If it is, then size is 32 bit, otherwise it's 16 bit. In this
Marko Mikulicic 0:c0ecb8bf28eb 11811 * example, we have 16-bit skips.
Marko Mikulicic 0:c0ecb8bf28eb 11812 *
Marko Mikulicic 0:c0ecb8bf28eb 11813 * The order of skips is determined by the `enum ast_which_skip`. If you
Marko Mikulicic 0:c0ecb8bf28eb 11814 * check, you'll see that `AST_END_SKIP` is 0, and `AST_VAR_NEXT_SKIP`
Marko Mikulicic 0:c0ecb8bf28eb 11815 * is 1. So, `end` skip fill be the first, and `next` will be the second:
Marko Mikulicic 0:c0ecb8bf28eb 11816 * - 00 09
Marko Mikulicic 0:c0ecb8bf28eb 11817 * `end` skip: 9 bytes. It's the size of the whole `SCRIPT` data. So, if
Marko Mikulicic 0:c0ecb8bf28eb 11818 * we have an index of the `ASC_SCRIPT` tag, we can just add this skip
Marko Mikulicic 0:c0ecb8bf28eb 11819 * (9) to this index, and therefore skip over the whole node.
Marko Mikulicic 0:c0ecb8bf28eb 11820 * - 00 00
Marko Mikulicic 0:c0ecb8bf28eb 11821 * `next` skip. `next` actually means "next variable node": since
Marko Mikulicic 0:c0ecb8bf28eb 11822 * variables are hoisted in JavaScript, when the interpreter starts
Marko Mikulicic 0:c0ecb8bf28eb 11823 * executing a top-level code or any function, it needs to get a list of
Marko Mikulicic 0:c0ecb8bf28eb 11824 * all defined variables. The `SCRIPT` node has a "skip" to the first
Marko Mikulicic 0:c0ecb8bf28eb 11825 * `var` or `function` declaration, which, in turn, has a "skip" to the
Marko Mikulicic 0:c0ecb8bf28eb 11826 * next one, etc. If there is no next `var` declaration, then 0 is
Marko Mikulicic 0:c0ecb8bf28eb 11827 * stored.
Marko Mikulicic 0:c0ecb8bf28eb 11828 *
Marko Mikulicic 0:c0ecb8bf28eb 11829 * In our super-simple script, we have no `var` neither `function`
Marko Mikulicic 0:c0ecb8bf28eb 11830 * declarations, so, this skip is 0.
Marko Mikulicic 0:c0ecb8bf28eb 11831 *
Marko Mikulicic 0:c0ecb8bf28eb 11832 * Now, the body of our SCRIPT node goes, which contains child nodes:
Marko Mikulicic 0:c0ecb8bf28eb 11833 *
Marko Mikulicic 0:c0ecb8bf28eb 11834 * - 13
Marko Mikulicic 0:c0ecb8bf28eb 11835 * AST tag: `AST_NUM`. Look at the `ast_node_defs`, and we'll see that
Marko Mikulicic 0:c0ecb8bf28eb 11836 * nodes of this type don't have any skips, but they do have the varint
Marko Mikulicic 0:c0ecb8bf28eb 11837 * field and the inlined data. Here we go:
Marko Mikulicic 0:c0ecb8bf28eb 11838 * - 03
Marko Mikulicic 0:c0ecb8bf28eb 11839 * Varint value: 3
Marko Mikulicic 0:c0ecb8bf28eb 11840 * - 33 30 30
Marko Mikulicic 0:c0ecb8bf28eb 11841 * UTF-8 string "300"
Marko Mikulicic 0:c0ecb8bf28eb 11842 *
Marko Mikulicic 0:c0ecb8bf28eb 11843 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 11844 *
Marko Mikulicic 0:c0ecb8bf28eb 11845 * The next example is a bit more interesting:
Marko Mikulicic 0:c0ecb8bf28eb 11846 *
Marko Mikulicic 0:c0ecb8bf28eb 11847 * var foo,
Marko Mikulicic 0:c0ecb8bf28eb 11848 * bar = 1;
Marko Mikulicic 0:c0ecb8bf28eb 11849 * foo = 3;
Marko Mikulicic 0:c0ecb8bf28eb 11850 * var baz = 4;
Marko Mikulicic 0:c0ecb8bf28eb 11851 *
Marko Mikulicic 0:c0ecb8bf28eb 11852 * Tree:
Marko Mikulicic 0:c0ecb8bf28eb 11853 *
Marko Mikulicic 0:c0ecb8bf28eb 11854 * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -t
Marko Mikulicic 0:c0ecb8bf28eb 11855 * SCRIPT
Marko Mikulicic 0:c0ecb8bf28eb 11856 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11857 * VAR
Marko Mikulicic 0:c0ecb8bf28eb 11858 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11859 * VAR_DECL foo
Marko Mikulicic 0:c0ecb8bf28eb 11860 * NOP
Marko Mikulicic 0:c0ecb8bf28eb 11861 * VAR_DECL bar
Marko Mikulicic 0:c0ecb8bf28eb 11862 * NUM 1
Marko Mikulicic 0:c0ecb8bf28eb 11863 * ASSIGN
Marko Mikulicic 0:c0ecb8bf28eb 11864 * IDENT foo
Marko Mikulicic 0:c0ecb8bf28eb 11865 * NUM 3
Marko Mikulicic 0:c0ecb8bf28eb 11866 * VAR
Marko Mikulicic 0:c0ecb8bf28eb 11867 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11868 * VAR_DECL baz
Marko Mikulicic 0:c0ecb8bf28eb 11869 * NUM 4
Marko Mikulicic 0:c0ecb8bf28eb 11870 *
Marko Mikulicic 0:c0ecb8bf28eb 11871 * Binary:
Marko Mikulicic 0:c0ecb8bf28eb 11872 *
Marko Mikulicic 0:c0ecb8bf28eb 11873 * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -b | od -A n -t x1
Marko Mikulicic 0:c0ecb8bf28eb 11874 * 56 07 41 53 54 56 31 30 00 01 00 2d 00 05 02 00
Marko Mikulicic 0:c0ecb8bf28eb 11875 * 12 00 1c 03 03 66 6f 6f 00 03 03 62 61 72 13 01
Marko Mikulicic 0:c0ecb8bf28eb 11876 * 31 07 14 03 66 6f 6f 13 01 33 02 00 0c 00 00 03
Marko Mikulicic 0:c0ecb8bf28eb 11877 * 03 62 61 7a 13 01 34
Marko Mikulicic 0:c0ecb8bf28eb 11878 *
Marko Mikulicic 0:c0ecb8bf28eb 11879 * Break it down:
Marko Mikulicic 0:c0ecb8bf28eb 11880 *
Marko Mikulicic 0:c0ecb8bf28eb 11881 * - 56 07 41 53 54 56 31 30 00
Marko Mikulicic 0:c0ecb8bf28eb 11882 * `"V\007ASTV10"`
Marko Mikulicic 0:c0ecb8bf28eb 11883 * - 01: AST tag: `AST_SCRIPT`
Marko Mikulicic 0:c0ecb8bf28eb 11884 * - 00 2d: `end` skip: 0x2d = 45 bytes
Marko Mikulicic 0:c0ecb8bf28eb 11885 * - 00 05: `next` skip: an offset from `AST_SCRIPT` byte to the first
Marko Mikulicic 0:c0ecb8bf28eb 11886 * `var` declaration.
Marko Mikulicic 0:c0ecb8bf28eb 11887 *
Marko Mikulicic 0:c0ecb8bf28eb 11888 * Now, body of the SCRIPT node begins, which contains child nodes,
Marko Mikulicic 0:c0ecb8bf28eb 11889 * and the first node is the var declaration `var foo, bar=1;`:
Marko Mikulicic 0:c0ecb8bf28eb 11890 *
Marko Mikulicic 0:c0ecb8bf28eb 11891 * SCRIPT node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11892 * - 02: AST tag: `AST_VAR`
Marko Mikulicic 0:c0ecb8bf28eb 11893 * - 00 12: `end` skip: 18 bytes from tag byte to the end of current node
Marko Mikulicic 0:c0ecb8bf28eb 11894 * - 00 1c: `next` skip: 28 bytes from tag byte to the next `var` node
Marko Mikulicic 0:c0ecb8bf28eb 11895 *
Marko Mikulicic 0:c0ecb8bf28eb 11896 * The VAR node contains arbitrary number of child nodes, so, consumer
Marko Mikulicic 0:c0ecb8bf28eb 11897 * takes advantage of the `end` skip.
Marko Mikulicic 0:c0ecb8bf28eb 11898 *
Marko Mikulicic 0:c0ecb8bf28eb 11899 * VAR node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11900 * - 03: AST tag: `AST_VAR_DECL`
Marko Mikulicic 0:c0ecb8bf28eb 11901 * - 03: Varint value: 3 (the length of the inlined data: a variable
Marko Mikulicic 0:c0ecb8bf28eb 11902 *name)
Marko Mikulicic 0:c0ecb8bf28eb 11903 * - 66 6f 6f: UTF-8 string: "foo"
Marko Mikulicic 0:c0ecb8bf28eb 11904 * - 00: AST tag: `AST_NOP`
Marko Mikulicic 0:c0ecb8bf28eb 11905 * Since we haven't provided any value to store into `foo`, NOP
Marko Mikulicic 0:c0ecb8bf28eb 11906 * without any additional data is stored in AST.
Marko Mikulicic 0:c0ecb8bf28eb 11907 *
Marko Mikulicic 0:c0ecb8bf28eb 11908 * - 03: AST tag: `AST_VAR_DECL`
Marko Mikulicic 0:c0ecb8bf28eb 11909 * - 03: Varint value: 3 (the length of the inlined data: a variable
Marko Mikulicic 0:c0ecb8bf28eb 11910 *name)
Marko Mikulicic 0:c0ecb8bf28eb 11911 * - 62 61 72: UTF-8 string: "bar"
Marko Mikulicic 0:c0ecb8bf28eb 11912 * - 13: AST tag: `AST_NUM`
Marko Mikulicic 0:c0ecb8bf28eb 11913 * - 01: Varint value: 1
Marko Mikulicic 0:c0ecb8bf28eb 11914 * - 31: UTF-8 string "1"
Marko Mikulicic 0:c0ecb8bf28eb 11915 * VAR body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11916 *
Marko Mikulicic 0:c0ecb8bf28eb 11917 * - 07: AST tag: `AST_ASSIGN`
Marko Mikulicic 0:c0ecb8bf28eb 11918 *
Marko Mikulicic 0:c0ecb8bf28eb 11919 * The ASSIGN node has fixed number of subrees: 2 (lvalue and rvalue),
Marko Mikulicic 0:c0ecb8bf28eb 11920 * so there's no `end` skip.
Marko Mikulicic 0:c0ecb8bf28eb 11921 *
Marko Mikulicic 0:c0ecb8bf28eb 11922 * ASSIGN node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11923 * - 14: AST tag: `AST_IDENT`
Marko Mikulicic 0:c0ecb8bf28eb 11924 * - 03: Varint value: 3
Marko Mikulicic 0:c0ecb8bf28eb 11925 * - 66 6f 6f: UTF-8 string: "foo"
Marko Mikulicic 0:c0ecb8bf28eb 11926 *
Marko Mikulicic 0:c0ecb8bf28eb 11927 * - 13: AST tag: `AST_NUM`
Marko Mikulicic 0:c0ecb8bf28eb 11928 * - 01: Varint value: 1
Marko Mikulicic 0:c0ecb8bf28eb 11929 * - 33: UTF-8 string: "3"
Marko Mikulicic 0:c0ecb8bf28eb 11930 * ASSIGN body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11931 *
Marko Mikulicic 0:c0ecb8bf28eb 11932 * - 02: AST tag: `AST_VAR`
Marko Mikulicic 0:c0ecb8bf28eb 11933 * - 00 0c: `end` skip: 12 bytes from tag byte to the end of current node
Marko Mikulicic 0:c0ecb8bf28eb 11934 * - 00 00: `next` skip: no more `var` nodes
Marko Mikulicic 0:c0ecb8bf28eb 11935 *
Marko Mikulicic 0:c0ecb8bf28eb 11936 * VAR node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11937 * - 03: AST tag: `AST_VAR_DECL`
Marko Mikulicic 0:c0ecb8bf28eb 11938 * - 03: Varint value: 3 (the length of the inlined data: a variable
Marko Mikulicic 0:c0ecb8bf28eb 11939 *name)
Marko Mikulicic 0:c0ecb8bf28eb 11940 * - 62 61 7a: UTF-8 string: "baz"
Marko Mikulicic 0:c0ecb8bf28eb 11941 * - 13: AST tag: `AST_NUM`
Marko Mikulicic 0:c0ecb8bf28eb 11942 * - 01: Varint value: 1
Marko Mikulicic 0:c0ecb8bf28eb 11943 * - 34: UTF-8 string "4"
Marko Mikulicic 0:c0ecb8bf28eb 11944 * VAR body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11945 * SCRIPT body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11946 *
Marko Mikulicic 0:c0ecb8bf28eb 11947 * --------------------------
Marko Mikulicic 0:c0ecb8bf28eb 11948 */
Marko Mikulicic 0:c0ecb8bf28eb 11949
Marko Mikulicic 0:c0ecb8bf28eb 11950 const struct ast_node_def ast_node_defs[] = {
Marko Mikulicic 0:c0ecb8bf28eb 11951 AST_ENTRY("NOP", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 11952
Marko Mikulicic 0:c0ecb8bf28eb 11953 /*
Marko Mikulicic 0:c0ecb8bf28eb 11954 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11955 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11956 * ast_skip_t first_var;
Marko Mikulicic 0:c0ecb8bf28eb 11957 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 11958 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11959 * }
Marko Mikulicic 0:c0ecb8bf28eb 11960 */
Marko Mikulicic 0:c0ecb8bf28eb 11961 AST_ENTRY("SCRIPT", 0, 0, 2, 0),
Marko Mikulicic 0:c0ecb8bf28eb 11962 /*
Marko Mikulicic 0:c0ecb8bf28eb 11963 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11964 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11965 * ast_skip_t next;
Marko Mikulicic 0:c0ecb8bf28eb 11966 * child decls[];
Marko Mikulicic 0:c0ecb8bf28eb 11967 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11968 * }
Marko Mikulicic 0:c0ecb8bf28eb 11969 */
Marko Mikulicic 0:c0ecb8bf28eb 11970 AST_ENTRY("VAR", 0, 0, 2, 0),
Marko Mikulicic 0:c0ecb8bf28eb 11971 /*
Marko Mikulicic 0:c0ecb8bf28eb 11972 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11973 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 11974 * char name[len];
Marko Mikulicic 0:c0ecb8bf28eb 11975 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 11976 * }
Marko Mikulicic 0:c0ecb8bf28eb 11977 */
Marko Mikulicic 0:c0ecb8bf28eb 11978 AST_ENTRY("VAR_DECL", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 11979 /*
Marko Mikulicic 0:c0ecb8bf28eb 11980 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11981 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 11982 * char name[len];
Marko Mikulicic 0:c0ecb8bf28eb 11983 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 11984 * }
Marko Mikulicic 0:c0ecb8bf28eb 11985 */
Marko Mikulicic 0:c0ecb8bf28eb 11986 AST_ENTRY("FUNC_DECL", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 11987 /*
Marko Mikulicic 0:c0ecb8bf28eb 11988 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11989 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11990 * ast_skip_t end_true;
Marko Mikulicic 0:c0ecb8bf28eb 11991 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 11992 * child iftrue[];
Marko Mikulicic 0:c0ecb8bf28eb 11993 * end_true:
Marko Mikulicic 0:c0ecb8bf28eb 11994 * child iffalse[];
Marko Mikulicic 0:c0ecb8bf28eb 11995 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11996 * }
Marko Mikulicic 0:c0ecb8bf28eb 11997 */
Marko Mikulicic 0:c0ecb8bf28eb 11998 AST_ENTRY("IF", 0, 0, 2, 1),
Marko Mikulicic 0:c0ecb8bf28eb 11999 /*
Marko Mikulicic 0:c0ecb8bf28eb 12000 * TODO(mkm) distinguish function expressions
Marko Mikulicic 0:c0ecb8bf28eb 12001 * from function statements.
Marko Mikulicic 0:c0ecb8bf28eb 12002 * Function statements behave like vars and need a
Marko Mikulicic 0:c0ecb8bf28eb 12003 * next field for hoisting.
Marko Mikulicic 0:c0ecb8bf28eb 12004 * We can also ignore the name for function expressions
Marko Mikulicic 0:c0ecb8bf28eb 12005 * if it's only needed for debugging.
Marko Mikulicic 0:c0ecb8bf28eb 12006 *
Marko Mikulicic 0:c0ecb8bf28eb 12007 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12008 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12009 * ast_skip_t first_var;
Marko Mikulicic 0:c0ecb8bf28eb 12010 * ast_skip_t body;
Marko Mikulicic 0:c0ecb8bf28eb 12011 * child name;
Marko Mikulicic 0:c0ecb8bf28eb 12012 * child params[];
Marko Mikulicic 0:c0ecb8bf28eb 12013 * body:
Marko Mikulicic 0:c0ecb8bf28eb 12014 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12015 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12016 * }
Marko Mikulicic 0:c0ecb8bf28eb 12017 */
Marko Mikulicic 0:c0ecb8bf28eb 12018 AST_ENTRY("FUNC", 0, 0, 3, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12019 AST_ENTRY("ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12020 AST_ENTRY("REM_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12021 AST_ENTRY("MUL_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12022 AST_ENTRY("DIV_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12023 AST_ENTRY("XOR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12024 AST_ENTRY("PLUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12025 AST_ENTRY("MINUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12026 AST_ENTRY("OR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12027 AST_ENTRY("AND_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12028 AST_ENTRY("LSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12029 AST_ENTRY("RSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12030 AST_ENTRY("URSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12031 AST_ENTRY("NUM", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 12032 AST_ENTRY("IDENT", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 12033 AST_ENTRY("STRING", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 12034 AST_ENTRY("REGEX", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 12035 AST_ENTRY("LABEL", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 12036
Marko Mikulicic 0:c0ecb8bf28eb 12037 /*
Marko Mikulicic 0:c0ecb8bf28eb 12038 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12039 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12040 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12041 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12042 * }
Marko Mikulicic 0:c0ecb8bf28eb 12043 */
Marko Mikulicic 0:c0ecb8bf28eb 12044 AST_ENTRY("SEQ", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12045 /*
Marko Mikulicic 0:c0ecb8bf28eb 12046 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12047 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12048 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 12049 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12050 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12051 * }
Marko Mikulicic 0:c0ecb8bf28eb 12052 */
Marko Mikulicic 0:c0ecb8bf28eb 12053 AST_ENTRY("WHILE", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12054 /*
Marko Mikulicic 0:c0ecb8bf28eb 12055 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12056 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12057 * ast_skip_t cond;
Marko Mikulicic 0:c0ecb8bf28eb 12058 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12059 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 12060 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 12061 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12062 * }
Marko Mikulicic 0:c0ecb8bf28eb 12063 */
Marko Mikulicic 0:c0ecb8bf28eb 12064 AST_ENTRY("DOWHILE", 0, 0, 2, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12065 /*
Marko Mikulicic 0:c0ecb8bf28eb 12066 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12067 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12068 * ast_skip_t body;
Marko Mikulicic 0:c0ecb8bf28eb 12069 * child init;
Marko Mikulicic 0:c0ecb8bf28eb 12070 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 12071 * child iter;
Marko Mikulicic 0:c0ecb8bf28eb 12072 * body:
Marko Mikulicic 0:c0ecb8bf28eb 12073 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12074 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12075 * }
Marko Mikulicic 0:c0ecb8bf28eb 12076 */
Marko Mikulicic 0:c0ecb8bf28eb 12077 AST_ENTRY("FOR", 0, 0, 2, 3),
Marko Mikulicic 0:c0ecb8bf28eb 12078 /*
Marko Mikulicic 0:c0ecb8bf28eb 12079 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12080 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12081 * ast_skip_t dummy; // allows to quickly promote a for to a for in
Marko Mikulicic 0:c0ecb8bf28eb 12082 * child var;
Marko Mikulicic 0:c0ecb8bf28eb 12083 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12084 * child dummy;
Marko Mikulicic 0:c0ecb8bf28eb 12085 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12086 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12087 * }
Marko Mikulicic 0:c0ecb8bf28eb 12088 */
Marko Mikulicic 0:c0ecb8bf28eb 12089 AST_ENTRY("FOR_IN", 0, 0, 2, 3),
Marko Mikulicic 0:c0ecb8bf28eb 12090 AST_ENTRY("COND", 0, 0, 0, 3), /* struct { child cond, iftrue, iffalse; } */
Marko Mikulicic 0:c0ecb8bf28eb 12091 AST_ENTRY("DEBUGGER", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12092 AST_ENTRY("BREAK", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12093
Marko Mikulicic 0:c0ecb8bf28eb 12094 /*
Marko Mikulicic 0:c0ecb8bf28eb 12095 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12096 * child label; // TODO(mkm): inline
Marko Mikulicic 0:c0ecb8bf28eb 12097 * }
Marko Mikulicic 0:c0ecb8bf28eb 12098 */
Marko Mikulicic 0:c0ecb8bf28eb 12099 AST_ENTRY("LAB_BREAK", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12100 AST_ENTRY("CONTINUE", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12101
Marko Mikulicic 0:c0ecb8bf28eb 12102 /*
Marko Mikulicic 0:c0ecb8bf28eb 12103 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12104 * child label; // TODO(mkm): inline
Marko Mikulicic 0:c0ecb8bf28eb 12105 * }
Marko Mikulicic 0:c0ecb8bf28eb 12106 */
Marko Mikulicic 0:c0ecb8bf28eb 12107 AST_ENTRY("LAB_CONTINUE", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12108 AST_ENTRY("RETURN", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12109 AST_ENTRY("VAL_RETURN", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12110 AST_ENTRY("THROW", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12111
Marko Mikulicic 0:c0ecb8bf28eb 12112 /*
Marko Mikulicic 0:c0ecb8bf28eb 12113 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12114 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12115 * ast_skip_t catch;
Marko Mikulicic 0:c0ecb8bf28eb 12116 * ast_skip_t finally;
Marko Mikulicic 0:c0ecb8bf28eb 12117 * child try[];
Marko Mikulicic 0:c0ecb8bf28eb 12118 * catch:
Marko Mikulicic 0:c0ecb8bf28eb 12119 * child var; // TODO(mkm): inline
Marko Mikulicic 0:c0ecb8bf28eb 12120 * child catch[];
Marko Mikulicic 0:c0ecb8bf28eb 12121 * finally:
Marko Mikulicic 0:c0ecb8bf28eb 12122 * child finally[];
Marko Mikulicic 0:c0ecb8bf28eb 12123 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12124 * }
Marko Mikulicic 0:c0ecb8bf28eb 12125 */
Marko Mikulicic 0:c0ecb8bf28eb 12126 AST_ENTRY("TRY", 0, 0, 3, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12127 /*
Marko Mikulicic 0:c0ecb8bf28eb 12128 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12129 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12130 * ast_skip_t def;
Marko Mikulicic 0:c0ecb8bf28eb 12131 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12132 * child cases[];
Marko Mikulicic 0:c0ecb8bf28eb 12133 * def:
Marko Mikulicic 0:c0ecb8bf28eb 12134 * child default?; // optional
Marko Mikulicic 0:c0ecb8bf28eb 12135 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12136 * }
Marko Mikulicic 0:c0ecb8bf28eb 12137 */
Marko Mikulicic 0:c0ecb8bf28eb 12138 AST_ENTRY("SWITCH", 0, 0, 2, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12139 /*
Marko Mikulicic 0:c0ecb8bf28eb 12140 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12141 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12142 * child val;
Marko Mikulicic 0:c0ecb8bf28eb 12143 * child stmts[];
Marko Mikulicic 0:c0ecb8bf28eb 12144 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12145 * }
Marko Mikulicic 0:c0ecb8bf28eb 12146 */
Marko Mikulicic 0:c0ecb8bf28eb 12147 AST_ENTRY("CASE", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12148 /*
Marko Mikulicic 0:c0ecb8bf28eb 12149 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12150 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12151 * child stmts[];
Marko Mikulicic 0:c0ecb8bf28eb 12152 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12153 * }
Marko Mikulicic 0:c0ecb8bf28eb 12154 */
Marko Mikulicic 0:c0ecb8bf28eb 12155 AST_ENTRY("DEFAULT", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12156 /*
Marko Mikulicic 0:c0ecb8bf28eb 12157 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12158 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12159 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12160 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12161 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12162 * }
Marko Mikulicic 0:c0ecb8bf28eb 12163 */
Marko Mikulicic 0:c0ecb8bf28eb 12164 AST_ENTRY("WITH", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12165 AST_ENTRY("LOG_OR", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12166 AST_ENTRY("LOG_AND", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12167 AST_ENTRY("OR", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12168 AST_ENTRY("XOR", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12169 AST_ENTRY("AND", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12170 AST_ENTRY("EQ", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12171 AST_ENTRY("EQ_EQ", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12172 AST_ENTRY("NE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12173 AST_ENTRY("NE_NE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12174 AST_ENTRY("LE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12175 AST_ENTRY("LT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12176 AST_ENTRY("GE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12177 AST_ENTRY("GT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12178 AST_ENTRY("IN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12179 AST_ENTRY("INSTANCEOF", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12180 AST_ENTRY("LSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12181 AST_ENTRY("RSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12182 AST_ENTRY("URSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12183 AST_ENTRY("ADD", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12184 AST_ENTRY("SUB", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12185 AST_ENTRY("REM", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12186 AST_ENTRY("MUL", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12187 AST_ENTRY("DIV", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12188 AST_ENTRY("POS", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12189 AST_ENTRY("NEG", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12190 AST_ENTRY("NOT", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12191 AST_ENTRY("LOGICAL_NOT", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12192 AST_ENTRY("VOID", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12193 AST_ENTRY("DELETE", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12194 AST_ENTRY("TYPEOF", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12195 AST_ENTRY("PREINC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12196 AST_ENTRY("PREDEC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12197 AST_ENTRY("POSTINC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12198 AST_ENTRY("POSTDEC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12199
Marko Mikulicic 0:c0ecb8bf28eb 12200 /*
Marko Mikulicic 0:c0ecb8bf28eb 12201 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12202 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 12203 * char ident[len];
Marko Mikulicic 0:c0ecb8bf28eb 12204 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12205 * }
Marko Mikulicic 0:c0ecb8bf28eb 12206 */
Marko Mikulicic 0:c0ecb8bf28eb 12207 AST_ENTRY("MEMBER", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12208 /*
Marko Mikulicic 0:c0ecb8bf28eb 12209 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12210 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12211 * child index;
Marko Mikulicic 0:c0ecb8bf28eb 12212 * }
Marko Mikulicic 0:c0ecb8bf28eb 12213 */
Marko Mikulicic 0:c0ecb8bf28eb 12214 AST_ENTRY("INDEX", 0, 0, 0, 2),
Marko Mikulicic 0:c0ecb8bf28eb 12215 /*
Marko Mikulicic 0:c0ecb8bf28eb 12216 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12217 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12218 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12219 * child args[];
Marko Mikulicic 0:c0ecb8bf28eb 12220 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12221 * }
Marko Mikulicic 0:c0ecb8bf28eb 12222 */
Marko Mikulicic 0:c0ecb8bf28eb 12223 AST_ENTRY("CALL", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12224 /*
Marko Mikulicic 0:c0ecb8bf28eb 12225 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12226 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12227 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12228 * child args[];
Marko Mikulicic 0:c0ecb8bf28eb 12229 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12230 * }
Marko Mikulicic 0:c0ecb8bf28eb 12231 */
Marko Mikulicic 0:c0ecb8bf28eb 12232 AST_ENTRY("NEW", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12233 /*
Marko Mikulicic 0:c0ecb8bf28eb 12234 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12235 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12236 * child elements[];
Marko Mikulicic 0:c0ecb8bf28eb 12237 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12238 * }
Marko Mikulicic 0:c0ecb8bf28eb 12239 */
Marko Mikulicic 0:c0ecb8bf28eb 12240 AST_ENTRY("ARRAY", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12241 /*
Marko Mikulicic 0:c0ecb8bf28eb 12242 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12243 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12244 * child props[];
Marko Mikulicic 0:c0ecb8bf28eb 12245 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12246 * }
Marko Mikulicic 0:c0ecb8bf28eb 12247 */
Marko Mikulicic 0:c0ecb8bf28eb 12248 AST_ENTRY("OBJECT", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12249 /*
Marko Mikulicic 0:c0ecb8bf28eb 12250 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12251 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 12252 * char name[len];
Marko Mikulicic 0:c0ecb8bf28eb 12253 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12254 * }
Marko Mikulicic 0:c0ecb8bf28eb 12255 */
Marko Mikulicic 0:c0ecb8bf28eb 12256 AST_ENTRY("PROP", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12257 /*
Marko Mikulicic 0:c0ecb8bf28eb 12258 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12259 * child func;
Marko Mikulicic 0:c0ecb8bf28eb 12260 * }
Marko Mikulicic 0:c0ecb8bf28eb 12261 */
Marko Mikulicic 0:c0ecb8bf28eb 12262 AST_ENTRY("GETTER", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12263 /*
Marko Mikulicic 0:c0ecb8bf28eb 12264 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12265 * child func;
Marko Mikulicic 0:c0ecb8bf28eb 12266 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12267 * }
Marko Mikulicic 0:c0ecb8bf28eb 12268 */
Marko Mikulicic 0:c0ecb8bf28eb 12269 AST_ENTRY("SETTER", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12270 AST_ENTRY("THIS", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12271 AST_ENTRY("TRUE", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12272 AST_ENTRY("FALSE", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12273 AST_ENTRY("NULL", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12274 AST_ENTRY("UNDEF", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12275 AST_ENTRY("USE_STRICT", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12276 };
Marko Mikulicic 0:c0ecb8bf28eb 12277
Marko Mikulicic 0:c0ecb8bf28eb 12278 /*
Marko Mikulicic 0:c0ecb8bf28eb 12279 * A flag which is used to mark node's tag byte if the node has line number
Marko Mikulicic 0:c0ecb8bf28eb 12280 * data encoded (varint after skips). See `ast_get_line_no()`.
Marko Mikulicic 0:c0ecb8bf28eb 12281 */
Marko Mikulicic 0:c0ecb8bf28eb 12282 #define AST_TAG_LINENO_PRESENT 0x80
Marko Mikulicic 0:c0ecb8bf28eb 12283
Marko Mikulicic 0:c0ecb8bf28eb 12284 V7_STATIC_ASSERT(AST_MAX_TAG < 256, ast_tag_should_fit_in_char);
Marko Mikulicic 0:c0ecb8bf28eb 12285 V7_STATIC_ASSERT(AST_MAX_TAG == ARRAY_SIZE(ast_node_defs), bad_node_defs);
Marko Mikulicic 0:c0ecb8bf28eb 12286 V7_STATIC_ASSERT(AST_MAX_TAG <= AST_TAG_LINENO_PRESENT, bad_AST_LINE_NO);
Marko Mikulicic 0:c0ecb8bf28eb 12287
Marko Mikulicic 0:c0ecb8bf28eb 12288 #if V7_ENABLE_FOOTPRINT_REPORT
Marko Mikulicic 0:c0ecb8bf28eb 12289 const size_t ast_node_defs_size = sizeof(ast_node_defs);
Marko Mikulicic 0:c0ecb8bf28eb 12290 const size_t ast_node_defs_count = ARRAY_SIZE(ast_node_defs);
Marko Mikulicic 0:c0ecb8bf28eb 12291 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12292
Marko Mikulicic 0:c0ecb8bf28eb 12293 /*
Marko Mikulicic 0:c0ecb8bf28eb 12294 * Converts a given byte `t` (which should be read from the AST data buffer)
Marko Mikulicic 0:c0ecb8bf28eb 12295 * into `enum ast_tag`. This function is needed because tag might be marked
Marko Mikulicic 0:c0ecb8bf28eb 12296 * with the `AST_TAG_LINENO_PRESENT` flag; the returned tag is always unmarked,
Marko Mikulicic 0:c0ecb8bf28eb 12297 * and if the flag was indeed set, `lineno_present` is set to 1; otherwise
Marko Mikulicic 0:c0ecb8bf28eb 12298 * it is set to 0.
Marko Mikulicic 0:c0ecb8bf28eb 12299 *
Marko Mikulicic 0:c0ecb8bf28eb 12300 * `lineno_present` is allowed to be NULL, if the caller doesn't care of the
Marko Mikulicic 0:c0ecb8bf28eb 12301 * line number presence.
Marko Mikulicic 0:c0ecb8bf28eb 12302 */
Marko Mikulicic 0:c0ecb8bf28eb 12303 static enum ast_tag uint8_to_tag(uint8_t t, uint8_t *lineno_present) {
Marko Mikulicic 0:c0ecb8bf28eb 12304 if (t & AST_TAG_LINENO_PRESENT) {
Marko Mikulicic 0:c0ecb8bf28eb 12305 t &= ~AST_TAG_LINENO_PRESENT;
Marko Mikulicic 0:c0ecb8bf28eb 12306 if (lineno_present != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12307 *lineno_present = 1;
Marko Mikulicic 0:c0ecb8bf28eb 12308 }
Marko Mikulicic 0:c0ecb8bf28eb 12309 } else if (lineno_present != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12310 *lineno_present = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12311 }
Marko Mikulicic 0:c0ecb8bf28eb 12312 return (enum ast_tag) t;
Marko Mikulicic 0:c0ecb8bf28eb 12313 }
Marko Mikulicic 0:c0ecb8bf28eb 12314
Marko Mikulicic 0:c0ecb8bf28eb 12315 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 12316 ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 12317 uint8_t t = (uint8_t) tag;
Marko Mikulicic 0:c0ecb8bf28eb 12318 const struct ast_node_def *d = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12319 ast_off_t cur = pos;
Marko Mikulicic 0:c0ecb8bf28eb 12320
Marko Mikulicic 0:c0ecb8bf28eb 12321 assert(tag < AST_MAX_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 12322
Marko Mikulicic 0:c0ecb8bf28eb 12323 mbuf_insert(&a->mbuf, cur, (char *) &t, sizeof(t));
Marko Mikulicic 0:c0ecb8bf28eb 12324 cur += sizeof(t);
Marko Mikulicic 0:c0ecb8bf28eb 12325
Marko Mikulicic 0:c0ecb8bf28eb 12326 mbuf_insert(&a->mbuf, cur, NULL, sizeof(ast_skip_t) * d->num_skips);
Marko Mikulicic 0:c0ecb8bf28eb 12327 cur += sizeof(ast_skip_t) * d->num_skips;
Marko Mikulicic 0:c0ecb8bf28eb 12328
Marko Mikulicic 0:c0ecb8bf28eb 12329 if (d->num_skips) {
Marko Mikulicic 0:c0ecb8bf28eb 12330 ast_set_skip(a, pos + 1, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 12331 }
Marko Mikulicic 0:c0ecb8bf28eb 12332
Marko Mikulicic 0:c0ecb8bf28eb 12333 return pos + 1;
Marko Mikulicic 0:c0ecb8bf28eb 12334 }
Marko Mikulicic 0:c0ecb8bf28eb 12335
Marko Mikulicic 0:c0ecb8bf28eb 12336 V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off,
Marko Mikulicic 0:c0ecb8bf28eb 12337 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 12338 a->mbuf.buf[tag_off] = tag | (a->mbuf.buf[tag_off] & 0x80);
Marko Mikulicic 0:c0ecb8bf28eb 12339 }
Marko Mikulicic 0:c0ecb8bf28eb 12340
Marko Mikulicic 0:c0ecb8bf28eb 12341 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 12342 V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 12343 ast_off_t ln_off = tag_off + 1 /* tag byte */;
Marko Mikulicic 0:c0ecb8bf28eb 12344 int llen = calc_llen(line_no);
Marko Mikulicic 0:c0ecb8bf28eb 12345
Marko Mikulicic 0:c0ecb8bf28eb 12346 ast_move_to_inlined_data(a, &ln_off);
Marko Mikulicic 0:c0ecb8bf28eb 12347 mbuf_insert(&a->mbuf, ln_off, NULL, llen);
Marko Mikulicic 0:c0ecb8bf28eb 12348 encode_varint(line_no, (unsigned char *) (a->mbuf.buf + ln_off));
Marko Mikulicic 0:c0ecb8bf28eb 12349
Marko Mikulicic 0:c0ecb8bf28eb 12350 assert(a->mbuf.buf[tag_off] < AST_MAX_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 12351 a->mbuf.buf[tag_off] |= AST_TAG_LINENO_PRESENT;
Marko Mikulicic 0:c0ecb8bf28eb 12352 }
Marko Mikulicic 0:c0ecb8bf28eb 12353 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12354
Marko Mikulicic 0:c0ecb8bf28eb 12355 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 12356 ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) {
Marko Mikulicic 0:c0ecb8bf28eb 12357 return ast_modify_skip(a, pos, a->mbuf.len, skip);
Marko Mikulicic 0:c0ecb8bf28eb 12358 }
Marko Mikulicic 0:c0ecb8bf28eb 12359
Marko Mikulicic 0:c0ecb8bf28eb 12360 V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 12361 ast_off_t where,
Marko Mikulicic 0:c0ecb8bf28eb 12362 enum ast_which_skip skip) {
Marko Mikulicic 0:c0ecb8bf28eb 12363 uint8_t *p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12364 ast_skip_t delta = where - pos;
Marko Mikulicic 0:c0ecb8bf28eb 12365 #ifndef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 12366 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12367 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12368 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12369 assert(pos <= where);
Marko Mikulicic 0:c0ecb8bf28eb 12370
Marko Mikulicic 0:c0ecb8bf28eb 12371 #ifndef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 12372 /* the value of delta overflowed, therefore the ast is not useable */
Marko Mikulicic 0:c0ecb8bf28eb 12373 if (where - pos > AST_SKIP_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 12374 a->has_overflow = 1;
Marko Mikulicic 0:c0ecb8bf28eb 12375 }
Marko Mikulicic 0:c0ecb8bf28eb 12376 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12377
Marko Mikulicic 0:c0ecb8bf28eb 12378 /* assertion, to be optimizable out */
Marko Mikulicic 0:c0ecb8bf28eb 12379 assert((int) skip < def->num_skips);
Marko Mikulicic 0:c0ecb8bf28eb 12380
Marko Mikulicic 0:c0ecb8bf28eb 12381 #ifdef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 12382 p[0] = delta >> 24;
Marko Mikulicic 0:c0ecb8bf28eb 12383 p[1] = delta >> 16 & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12384 p[2] = delta >> 8 & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12385 p[3] = delta & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12386 #else
Marko Mikulicic 0:c0ecb8bf28eb 12387 p[0] = delta >> 8;
Marko Mikulicic 0:c0ecb8bf28eb 12388 p[1] = delta & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12389 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12390 return where;
Marko Mikulicic 0:c0ecb8bf28eb 12391 }
Marko Mikulicic 0:c0ecb8bf28eb 12392
Marko Mikulicic 0:c0ecb8bf28eb 12393 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 12394 ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) {
Marko Mikulicic 0:c0ecb8bf28eb 12395 uint8_t *p;
Marko Mikulicic 0:c0ecb8bf28eb 12396 assert(pos + skip * sizeof(ast_skip_t) < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12397
Marko Mikulicic 0:c0ecb8bf28eb 12398 p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12399 #ifdef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 12400 return pos + (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24);
Marko Mikulicic 0:c0ecb8bf28eb 12401 #else
Marko Mikulicic 0:c0ecb8bf28eb 12402 return pos + (p[1] | p[0] << 8);
Marko Mikulicic 0:c0ecb8bf28eb 12403 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12404 }
Marko Mikulicic 0:c0ecb8bf28eb 12405
Marko Mikulicic 0:c0ecb8bf28eb 12406 V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12407 enum ast_tag ret;
Marko Mikulicic 0:c0ecb8bf28eb 12408 assert(*ppos < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12409
Marko Mikulicic 0:c0ecb8bf28eb 12410 ret = uint8_to_tag(*(a->mbuf.buf + (*ppos)++), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12411
Marko Mikulicic 0:c0ecb8bf28eb 12412 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12413 }
Marko Mikulicic 0:c0ecb8bf28eb 12414
Marko Mikulicic 0:c0ecb8bf28eb 12415 V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12416 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12417 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12418 assert(*ppos - 1 < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12419
Marko Mikulicic 0:c0ecb8bf28eb 12420 ast_move_to_inlined_data(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12421
Marko Mikulicic 0:c0ecb8bf28eb 12422 /* skip varint + inline data, if present */
Marko Mikulicic 0:c0ecb8bf28eb 12423 if (def->has_varint) {
Marko Mikulicic 0:c0ecb8bf28eb 12424 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12425 size_t slen = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12426 *ppos += llen;
Marko Mikulicic 0:c0ecb8bf28eb 12427 if (def->has_inlined) {
Marko Mikulicic 0:c0ecb8bf28eb 12428 *ppos += slen;
Marko Mikulicic 0:c0ecb8bf28eb 12429 }
Marko Mikulicic 0:c0ecb8bf28eb 12430 }
Marko Mikulicic 0:c0ecb8bf28eb 12431 }
Marko Mikulicic 0:c0ecb8bf28eb 12432
Marko Mikulicic 0:c0ecb8bf28eb 12433 V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 12434 enum ast_tag tag, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 12435 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 12436 const struct ast_node_def *d = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12437
Marko Mikulicic 0:c0ecb8bf28eb 12438 ast_off_t offset = ast_insert_node(a, pos, tag);
Marko Mikulicic 0:c0ecb8bf28eb 12439
Marko Mikulicic 0:c0ecb8bf28eb 12440 assert(d->has_inlined);
Marko Mikulicic 0:c0ecb8bf28eb 12441
Marko Mikulicic 0:c0ecb8bf28eb 12442 embed_string(&a->mbuf, offset + sizeof(ast_skip_t) * d->num_skips, name, len,
Marko Mikulicic 0:c0ecb8bf28eb 12443 EMBSTR_UNESCAPE);
Marko Mikulicic 0:c0ecb8bf28eb 12444
Marko Mikulicic 0:c0ecb8bf28eb 12445 return offset;
Marko Mikulicic 0:c0ecb8bf28eb 12446 }
Marko Mikulicic 0:c0ecb8bf28eb 12447
Marko Mikulicic 0:c0ecb8bf28eb 12448 V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos) {
Marko Mikulicic 0:c0ecb8bf28eb 12449 /*
Marko Mikulicic 0:c0ecb8bf28eb 12450 * by default we'll return 0, meaning that the AST node does not contain line
Marko Mikulicic 0:c0ecb8bf28eb 12451 * number data
Marko Mikulicic 0:c0ecb8bf28eb 12452 */
Marko Mikulicic 0:c0ecb8bf28eb 12453 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12454
Marko Mikulicic 0:c0ecb8bf28eb 12455 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 12456 uint8_t lineno_present;
Marko Mikulicic 0:c0ecb8bf28eb 12457 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), &lineno_present);
Marko Mikulicic 0:c0ecb8bf28eb 12458
Marko Mikulicic 0:c0ecb8bf28eb 12459 if (lineno_present) {
Marko Mikulicic 0:c0ecb8bf28eb 12460 /* line number is present, so, let's decode it */
Marko Mikulicic 0:c0ecb8bf28eb 12461 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12462
Marko Mikulicic 0:c0ecb8bf28eb 12463 /* skip skips */
Marko Mikulicic 0:c0ecb8bf28eb 12464 pos += ast_node_defs[tag].num_skips * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12465
Marko Mikulicic 0:c0ecb8bf28eb 12466 /* get line number */
Marko Mikulicic 0:c0ecb8bf28eb 12467 ret = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12468 }
Marko Mikulicic 0:c0ecb8bf28eb 12469 #else
Marko Mikulicic 0:c0ecb8bf28eb 12470 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 12471 (void) pos;
Marko Mikulicic 0:c0ecb8bf28eb 12472 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12473
Marko Mikulicic 0:c0ecb8bf28eb 12474 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12475 }
Marko Mikulicic 0:c0ecb8bf28eb 12476
Marko Mikulicic 0:c0ecb8bf28eb 12477 V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12478 uint8_t lineno_present = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12479 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), &lineno_present);
Marko Mikulicic 0:c0ecb8bf28eb 12480 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12481 assert(*ppos - 1 < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12482
Marko Mikulicic 0:c0ecb8bf28eb 12483 /* skip skips */
Marko Mikulicic 0:c0ecb8bf28eb 12484 *ppos += def->num_skips * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12485
Marko Mikulicic 0:c0ecb8bf28eb 12486 /* skip line_no, if present */
Marko Mikulicic 0:c0ecb8bf28eb 12487 if (lineno_present) {
Marko Mikulicic 0:c0ecb8bf28eb 12488 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12489 int line_no = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12490 *ppos += llen;
Marko Mikulicic 0:c0ecb8bf28eb 12491
Marko Mikulicic 0:c0ecb8bf28eb 12492 (void) line_no;
Marko Mikulicic 0:c0ecb8bf28eb 12493 }
Marko Mikulicic 0:c0ecb8bf28eb 12494 }
Marko Mikulicic 0:c0ecb8bf28eb 12495
Marko Mikulicic 0:c0ecb8bf28eb 12496 V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n) {
Marko Mikulicic 0:c0ecb8bf28eb 12497 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12498 assert(pos < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12499
Marko Mikulicic 0:c0ecb8bf28eb 12500 ast_move_to_inlined_data(a, &pos);
Marko Mikulicic 0:c0ecb8bf28eb 12501
Marko Mikulicic 0:c0ecb8bf28eb 12502 *n = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12503 return a->mbuf.buf + pos + llen;
Marko Mikulicic 0:c0ecb8bf28eb 12504 }
Marko Mikulicic 0:c0ecb8bf28eb 12505
Marko Mikulicic 0:c0ecb8bf28eb 12506 V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos) {
Marko Mikulicic 0:c0ecb8bf28eb 12507 double ret;
Marko Mikulicic 0:c0ecb8bf28eb 12508 char *str;
Marko Mikulicic 0:c0ecb8bf28eb 12509 size_t str_len;
Marko Mikulicic 0:c0ecb8bf28eb 12510 char buf[12];
Marko Mikulicic 0:c0ecb8bf28eb 12511 char *p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 12512 str = ast_get_inlined_data(a, pos, &str_len);
Marko Mikulicic 0:c0ecb8bf28eb 12513 assert(str + str_len <= a->mbuf.buf + a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12514
Marko Mikulicic 0:c0ecb8bf28eb 12515 if (str_len > sizeof(buf) - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 12516 p = (char *) malloc(str_len + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12517 }
Marko Mikulicic 0:c0ecb8bf28eb 12518 strncpy(p, str, str_len);
Marko Mikulicic 0:c0ecb8bf28eb 12519 p[str_len] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 12520 ret = cs_strtod(p, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12521 if (p != buf) free(p);
Marko Mikulicic 0:c0ecb8bf28eb 12522 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12523 }
Marko Mikulicic 0:c0ecb8bf28eb 12524
Marko Mikulicic 0:c0ecb8bf28eb 12525 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 12526 static void comment_at_depth(FILE *fp, const char *fmt, int depth, ...) {
Marko Mikulicic 0:c0ecb8bf28eb 12527 int i;
Marko Mikulicic 0:c0ecb8bf28eb 12528 STATIC char buf[256];
Marko Mikulicic 0:c0ecb8bf28eb 12529 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 12530 va_start(ap, depth);
Marko Mikulicic 0:c0ecb8bf28eb 12531
Marko Mikulicic 0:c0ecb8bf28eb 12532 c_vsnprintf(buf, sizeof(buf), fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 12533
Marko Mikulicic 0:c0ecb8bf28eb 12534 for (i = 0; i < depth; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12535 fprintf(fp, " ");
Marko Mikulicic 0:c0ecb8bf28eb 12536 }
Marko Mikulicic 0:c0ecb8bf28eb 12537 fprintf(fp, "/* [%s] */\n", buf);
Marko Mikulicic 0:c0ecb8bf28eb 12538 }
Marko Mikulicic 0:c0ecb8bf28eb 12539 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12540
Marko Mikulicic 0:c0ecb8bf28eb 12541 V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12542 enum ast_tag tag = ast_fetch_tag(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12543 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12544 ast_off_t skips = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 12545 int i;
Marko Mikulicic 0:c0ecb8bf28eb 12546 ast_move_to_children(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12547
Marko Mikulicic 0:c0ecb8bf28eb 12548 for (i = 0; i < def->num_subtrees; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12549 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12550 }
Marko Mikulicic 0:c0ecb8bf28eb 12551
Marko Mikulicic 0:c0ecb8bf28eb 12552 if (def->num_skips > AST_END_SKIP) {
Marko Mikulicic 0:c0ecb8bf28eb 12553 ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 12554
Marko Mikulicic 0:c0ecb8bf28eb 12555 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 12556 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12557 }
Marko Mikulicic 0:c0ecb8bf28eb 12558 }
Marko Mikulicic 0:c0ecb8bf28eb 12559 }
Marko Mikulicic 0:c0ecb8bf28eb 12560
Marko Mikulicic 0:c0ecb8bf28eb 12561 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 12562 V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 12563 int depth) {
Marko Mikulicic 0:c0ecb8bf28eb 12564 enum ast_tag tag = ast_fetch_tag(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12565 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12566 ast_off_t skips = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 12567 size_t slen;
Marko Mikulicic 0:c0ecb8bf28eb 12568 int i, llen;
Marko Mikulicic 0:c0ecb8bf28eb 12569
Marko Mikulicic 0:c0ecb8bf28eb 12570 for (i = 0; i < depth; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12571 fprintf(fp, " ");
Marko Mikulicic 0:c0ecb8bf28eb 12572 }
Marko Mikulicic 0:c0ecb8bf28eb 12573
Marko Mikulicic 0:c0ecb8bf28eb 12574 #ifndef V7_DISABLE_AST_TAG_NAMES
Marko Mikulicic 0:c0ecb8bf28eb 12575 fprintf(fp, "%s", def->name);
Marko Mikulicic 0:c0ecb8bf28eb 12576 #else
Marko Mikulicic 0:c0ecb8bf28eb 12577 fprintf(fp, "TAG_%d", tag);
Marko Mikulicic 0:c0ecb8bf28eb 12578 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12579
Marko Mikulicic 0:c0ecb8bf28eb 12580 if (def->has_inlined) {
Marko Mikulicic 0:c0ecb8bf28eb 12581 ast_off_t pos_tmp = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 12582 ast_move_to_inlined_data(a, &pos_tmp);
Marko Mikulicic 0:c0ecb8bf28eb 12583
Marko Mikulicic 0:c0ecb8bf28eb 12584 slen = decode_varint((unsigned char *) a->mbuf.buf + pos_tmp, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12585 fprintf(fp, " %.*s\n", (int) slen, a->mbuf.buf + pos_tmp + llen);
Marko Mikulicic 0:c0ecb8bf28eb 12586 } else {
Marko Mikulicic 0:c0ecb8bf28eb 12587 fprintf(fp, "\n");
Marko Mikulicic 0:c0ecb8bf28eb 12588 }
Marko Mikulicic 0:c0ecb8bf28eb 12589
Marko Mikulicic 0:c0ecb8bf28eb 12590 ast_move_to_children(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12591
Marko Mikulicic 0:c0ecb8bf28eb 12592 for (i = 0; i < def->num_subtrees; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12593 ast_dump_tree(fp, a, ppos, depth + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12594 }
Marko Mikulicic 0:c0ecb8bf28eb 12595
Marko Mikulicic 0:c0ecb8bf28eb 12596 if (ast_node_defs[tag].num_skips) {
Marko Mikulicic 0:c0ecb8bf28eb 12597 /*
Marko Mikulicic 0:c0ecb8bf28eb 12598 * first skip always encodes end of the last children sequence.
Marko Mikulicic 0:c0ecb8bf28eb 12599 * so unless we care how the subtree sequences are grouped together
Marko Mikulicic 0:c0ecb8bf28eb 12600 * (and we currently don't) we can just read until the end of that skip.
Marko Mikulicic 0:c0ecb8bf28eb 12601 */
Marko Mikulicic 0:c0ecb8bf28eb 12602 ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 12603
Marko Mikulicic 0:c0ecb8bf28eb 12604 comment_at_depth(fp, "...", depth + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12605 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 12606 int s;
Marko Mikulicic 0:c0ecb8bf28eb 12607 for (s = ast_node_defs[tag].num_skips - 1; s > 0; s--) {
Marko Mikulicic 0:c0ecb8bf28eb 12608 if (*ppos == ast_get_skip(a, skips, (enum ast_which_skip) s)) {
Marko Mikulicic 0:c0ecb8bf28eb 12609 comment_at_depth(fp, "%d ->", depth + 1, s);
Marko Mikulicic 0:c0ecb8bf28eb 12610 break;
Marko Mikulicic 0:c0ecb8bf28eb 12611 }
Marko Mikulicic 0:c0ecb8bf28eb 12612 }
Marko Mikulicic 0:c0ecb8bf28eb 12613 ast_dump_tree(fp, a, ppos, depth + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12614 }
Marko Mikulicic 0:c0ecb8bf28eb 12615 }
Marko Mikulicic 0:c0ecb8bf28eb 12616 }
Marko Mikulicic 0:c0ecb8bf28eb 12617 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12618
Marko Mikulicic 0:c0ecb8bf28eb 12619 V7_PRIVATE void ast_init(struct ast *ast, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 12620 mbuf_init(&ast->mbuf, len);
Marko Mikulicic 0:c0ecb8bf28eb 12621 ast->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12622 ast->has_overflow = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12623 }
Marko Mikulicic 0:c0ecb8bf28eb 12624
Marko Mikulicic 0:c0ecb8bf28eb 12625 V7_PRIVATE void ast_optimize(struct ast *ast) {
Marko Mikulicic 0:c0ecb8bf28eb 12626 /*
Marko Mikulicic 0:c0ecb8bf28eb 12627 * leave one trailing byte so that literals can be
Marko Mikulicic 0:c0ecb8bf28eb 12628 * null terminated on the fly.
Marko Mikulicic 0:c0ecb8bf28eb 12629 */
Marko Mikulicic 0:c0ecb8bf28eb 12630 mbuf_resize(&ast->mbuf, ast->mbuf.len + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12631 }
Marko Mikulicic 0:c0ecb8bf28eb 12632
Marko Mikulicic 0:c0ecb8bf28eb 12633 V7_PRIVATE void ast_free(struct ast *ast) {
Marko Mikulicic 0:c0ecb8bf28eb 12634 mbuf_free(&ast->mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 12635 ast->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12636 ast->has_overflow = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12637 }
Marko Mikulicic 0:c0ecb8bf28eb 12638
Marko Mikulicic 0:c0ecb8bf28eb 12639 V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a) {
Marko Mikulicic 0:c0ecb8bf28eb 12640 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12641
Marko Mikulicic 0:c0ecb8bf28eb 12642 if (a->refcnt != 0) a->refcnt--;
Marko Mikulicic 0:c0ecb8bf28eb 12643
Marko Mikulicic 0:c0ecb8bf28eb 12644 if (a->refcnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 12645 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12646 v7->function_arena_ast_size -= a->mbuf.size;
Marko Mikulicic 0:c0ecb8bf28eb 12647 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12648 ast_free(a);
Marko Mikulicic 0:c0ecb8bf28eb 12649 free(a);
Marko Mikulicic 0:c0ecb8bf28eb 12650 }
Marko Mikulicic 0:c0ecb8bf28eb 12651 }
Marko Mikulicic 0:c0ecb8bf28eb 12652
Marko Mikulicic 0:c0ecb8bf28eb 12653 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 12654 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 12655 #line 1 "v7/src/bcode.c"
Marko Mikulicic 0:c0ecb8bf28eb 12656 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12657 /*
Marko Mikulicic 0:c0ecb8bf28eb 12658 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 12659 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 12660 */
Marko Mikulicic 0:c0ecb8bf28eb 12661
Marko Mikulicic 0:c0ecb8bf28eb 12662 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12663 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12664 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12665 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12666 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12667 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12668 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12669 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12670 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12671 /* Amalgamated: #include "v7/src/shdata.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12672
Marko Mikulicic 0:c0ecb8bf28eb 12673 /*
Marko Mikulicic 0:c0ecb8bf28eb 12674 * TODO(dfrank): implement `bcode_serialize_*` more generically, so that they
Marko Mikulicic 0:c0ecb8bf28eb 12675 * can write to buffer instead of a `FILE`. Then, remove a need for mmap here.
Marko Mikulicic 0:c0ecb8bf28eb 12676 */
Marko Mikulicic 0:c0ecb8bf28eb 12677 #if CS_PLATFORM == CS_P_UNIX
Marko Mikulicic 0:c0ecb8bf28eb 12678 #include <sys/mman.h>
Marko Mikulicic 0:c0ecb8bf28eb 12679 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12680
Marko Mikulicic 0:c0ecb8bf28eb 12681 #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 12682 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 12683 static const char *op_names[] = {
Marko Mikulicic 0:c0ecb8bf28eb 12684 "DROP",
Marko Mikulicic 0:c0ecb8bf28eb 12685 "DUP",
Marko Mikulicic 0:c0ecb8bf28eb 12686 "2DUP",
Marko Mikulicic 0:c0ecb8bf28eb 12687 "SWAP",
Marko Mikulicic 0:c0ecb8bf28eb 12688 "STASH",
Marko Mikulicic 0:c0ecb8bf28eb 12689 "UNSTASH",
Marko Mikulicic 0:c0ecb8bf28eb 12690 "SWAP_DROP",
Marko Mikulicic 0:c0ecb8bf28eb 12691 "PUSH_UNDEFINED",
Marko Mikulicic 0:c0ecb8bf28eb 12692 "PUSH_NULL",
Marko Mikulicic 0:c0ecb8bf28eb 12693 "PUSH_THIS",
Marko Mikulicic 0:c0ecb8bf28eb 12694 "PUSH_TRUE",
Marko Mikulicic 0:c0ecb8bf28eb 12695 "PUSH_FALSE",
Marko Mikulicic 0:c0ecb8bf28eb 12696 "PUSH_ZERO",
Marko Mikulicic 0:c0ecb8bf28eb 12697 "PUSH_ONE",
Marko Mikulicic 0:c0ecb8bf28eb 12698 "PUSH_LIT",
Marko Mikulicic 0:c0ecb8bf28eb 12699 "NOT",
Marko Mikulicic 0:c0ecb8bf28eb 12700 "LOGICAL_NOT",
Marko Mikulicic 0:c0ecb8bf28eb 12701 "NEG",
Marko Mikulicic 0:c0ecb8bf28eb 12702 "POS",
Marko Mikulicic 0:c0ecb8bf28eb 12703 "ADD",
Marko Mikulicic 0:c0ecb8bf28eb 12704 "SUB",
Marko Mikulicic 0:c0ecb8bf28eb 12705 "REM",
Marko Mikulicic 0:c0ecb8bf28eb 12706 "MUL",
Marko Mikulicic 0:c0ecb8bf28eb 12707 "DIV",
Marko Mikulicic 0:c0ecb8bf28eb 12708 "LSHIFT",
Marko Mikulicic 0:c0ecb8bf28eb 12709 "RSHIFT",
Marko Mikulicic 0:c0ecb8bf28eb 12710 "URSHIFT",
Marko Mikulicic 0:c0ecb8bf28eb 12711 "OR",
Marko Mikulicic 0:c0ecb8bf28eb 12712 "XOR",
Marko Mikulicic 0:c0ecb8bf28eb 12713 "AND",
Marko Mikulicic 0:c0ecb8bf28eb 12714 "EQ_EQ",
Marko Mikulicic 0:c0ecb8bf28eb 12715 "EQ",
Marko Mikulicic 0:c0ecb8bf28eb 12716 "NE",
Marko Mikulicic 0:c0ecb8bf28eb 12717 "NE_NE",
Marko Mikulicic 0:c0ecb8bf28eb 12718 "LT",
Marko Mikulicic 0:c0ecb8bf28eb 12719 "LE",
Marko Mikulicic 0:c0ecb8bf28eb 12720 "GT",
Marko Mikulicic 0:c0ecb8bf28eb 12721 "GE",
Marko Mikulicic 0:c0ecb8bf28eb 12722 "INSTANCEOF",
Marko Mikulicic 0:c0ecb8bf28eb 12723 "TYPEOF",
Marko Mikulicic 0:c0ecb8bf28eb 12724 "IN",
Marko Mikulicic 0:c0ecb8bf28eb 12725 "GET",
Marko Mikulicic 0:c0ecb8bf28eb 12726 "SET",
Marko Mikulicic 0:c0ecb8bf28eb 12727 "SET_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12728 "GET_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12729 "SAFE_GET_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12730 "JMP",
Marko Mikulicic 0:c0ecb8bf28eb 12731 "JMP_TRUE",
Marko Mikulicic 0:c0ecb8bf28eb 12732 "JMP_FALSE",
Marko Mikulicic 0:c0ecb8bf28eb 12733 "JMP_TRUE_DROP",
Marko Mikulicic 0:c0ecb8bf28eb 12734 "JMP_IF_CONTINUE",
Marko Mikulicic 0:c0ecb8bf28eb 12735 "CREATE_OBJ",
Marko Mikulicic 0:c0ecb8bf28eb 12736 "CREATE_ARR",
Marko Mikulicic 0:c0ecb8bf28eb 12737 "PUSH_PROP_ITER_CTX",
Marko Mikulicic 0:c0ecb8bf28eb 12738 "NEXT_PROP",
Marko Mikulicic 0:c0ecb8bf28eb 12739 "FUNC_LIT",
Marko Mikulicic 0:c0ecb8bf28eb 12740 "CALL",
Marko Mikulicic 0:c0ecb8bf28eb 12741 "NEW",
Marko Mikulicic 0:c0ecb8bf28eb 12742 "CHECK_CALL",
Marko Mikulicic 0:c0ecb8bf28eb 12743 "RET",
Marko Mikulicic 0:c0ecb8bf28eb 12744 "DELETE",
Marko Mikulicic 0:c0ecb8bf28eb 12745 "DELETE_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12746 "TRY_PUSH_CATCH",
Marko Mikulicic 0:c0ecb8bf28eb 12747 "TRY_PUSH_FINALLY",
Marko Mikulicic 0:c0ecb8bf28eb 12748 "TRY_PUSH_LOOP",
Marko Mikulicic 0:c0ecb8bf28eb 12749 "TRY_PUSH_SWITCH",
Marko Mikulicic 0:c0ecb8bf28eb 12750 "TRY_POP",
Marko Mikulicic 0:c0ecb8bf28eb 12751 "AFTER_FINALLY",
Marko Mikulicic 0:c0ecb8bf28eb 12752 "THROW",
Marko Mikulicic 0:c0ecb8bf28eb 12753 "BREAK",
Marko Mikulicic 0:c0ecb8bf28eb 12754 "CONTINUE",
Marko Mikulicic 0:c0ecb8bf28eb 12755 "ENTER_CATCH",
Marko Mikulicic 0:c0ecb8bf28eb 12756 "EXIT_CATCH",
Marko Mikulicic 0:c0ecb8bf28eb 12757 };
Marko Mikulicic 0:c0ecb8bf28eb 12758 /* clang-format on */
Marko Mikulicic 0:c0ecb8bf28eb 12759
Marko Mikulicic 0:c0ecb8bf28eb 12760 V7_STATIC_ASSERT(OP_MAX == ARRAY_SIZE(op_names), bad_op_names);
Marko Mikulicic 0:c0ecb8bf28eb 12761 V7_STATIC_ASSERT(OP_MAX <= _OP_LINE_NO, bad_OP_LINE_NO);
Marko Mikulicic 0:c0ecb8bf28eb 12762 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12763
Marko Mikulicic 0:c0ecb8bf28eb 12764 static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode, FILE *out);
Marko Mikulicic 0:c0ecb8bf28eb 12765
Marko Mikulicic 0:c0ecb8bf28eb 12766 static size_t bcode_ops_append(struct bcode_builder *bbuilder, const void *buf,
Marko Mikulicic 0:c0ecb8bf28eb 12767 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 12768 size_t ret;
Marko Mikulicic 0:c0ecb8bf28eb 12769 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12770 bbuilder->v7->bcode_ops_size -= bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12771 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12772 ret = mbuf_append(&bbuilder->ops, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 12773 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12774 bbuilder->v7->bcode_ops_size += bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12775 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12776 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12777 }
Marko Mikulicic 0:c0ecb8bf28eb 12778
Marko Mikulicic 0:c0ecb8bf28eb 12779 /*
Marko Mikulicic 0:c0ecb8bf28eb 12780 * Initialize bcode builder. The `bcode` should be already initialized by the
Marko Mikulicic 0:c0ecb8bf28eb 12781 * caller, and should be empty (i.e. should not own any ops, literals, etc)
Marko Mikulicic 0:c0ecb8bf28eb 12782 *
Marko Mikulicic 0:c0ecb8bf28eb 12783 * TODO(dfrank) : probably make `bcode_builder_init()` to initialize `bcode`
Marko Mikulicic 0:c0ecb8bf28eb 12784 * as well
Marko Mikulicic 0:c0ecb8bf28eb 12785 */
Marko Mikulicic 0:c0ecb8bf28eb 12786 V7_PRIVATE void bcode_builder_init(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 12787 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 12788 struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12789 memset(bbuilder, 0x00, sizeof(*bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 12790 bbuilder->v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 12791 bbuilder->bcode = bcode;
Marko Mikulicic 0:c0ecb8bf28eb 12792
Marko Mikulicic 0:c0ecb8bf28eb 12793 mbuf_init(&bbuilder->ops, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12794 mbuf_init(&bbuilder->lit, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12795 }
Marko Mikulicic 0:c0ecb8bf28eb 12796
Marko Mikulicic 0:c0ecb8bf28eb 12797 /*
Marko Mikulicic 0:c0ecb8bf28eb 12798 * Finalize bcode builder: propagate data to the bcode and transfer the
Marko Mikulicic 0:c0ecb8bf28eb 12799 * ownership from builder to bcode
Marko Mikulicic 0:c0ecb8bf28eb 12800 */
Marko Mikulicic 0:c0ecb8bf28eb 12801 V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder) {
Marko Mikulicic 0:c0ecb8bf28eb 12802 mbuf_trim(&bbuilder->ops);
Marko Mikulicic 0:c0ecb8bf28eb 12803 bbuilder->bcode->ops.p = bbuilder->ops.buf;
Marko Mikulicic 0:c0ecb8bf28eb 12804 bbuilder->bcode->ops.len = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12805 mbuf_init(&bbuilder->ops, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12806
Marko Mikulicic 0:c0ecb8bf28eb 12807 mbuf_trim(&bbuilder->lit);
Marko Mikulicic 0:c0ecb8bf28eb 12808 bbuilder->bcode->lit.p = bbuilder->lit.buf;
Marko Mikulicic 0:c0ecb8bf28eb 12809 bbuilder->bcode->lit.len = bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12810 mbuf_init(&bbuilder->lit, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12811
Marko Mikulicic 0:c0ecb8bf28eb 12812 memset(bbuilder, 0x00, sizeof(*bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 12813 }
Marko Mikulicic 0:c0ecb8bf28eb 12814
Marko Mikulicic 0:c0ecb8bf28eb 12815 #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 12816 V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 12817 char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 12818 char *p = *ops;
Marko Mikulicic 0:c0ecb8bf28eb 12819
Marko Mikulicic 0:c0ecb8bf28eb 12820 assert(*p < OP_MAX);
Marko Mikulicic 0:c0ecb8bf28eb 12821 fprintf(f, "%zu: %s", (size_t)(p - bcode->ops.p), op_names[(uint8_t) *p]);
Marko Mikulicic 0:c0ecb8bf28eb 12822 switch (*p) {
Marko Mikulicic 0:c0ecb8bf28eb 12823 case OP_PUSH_LIT:
Marko Mikulicic 0:c0ecb8bf28eb 12824 case OP_SAFE_GET_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 12825 case OP_GET_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 12826 case OP_SET_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 12827 size_t idx = bcode_get_varint(&p);
Marko Mikulicic 0:c0ecb8bf28eb 12828 fprintf(f, "(%lu): ", (unsigned long) idx);
Marko Mikulicic 0:c0ecb8bf28eb 12829 v7_fprint(f, v7, ((val_t *) bcode->lit.p)[idx]);
Marko Mikulicic 0:c0ecb8bf28eb 12830 break;
Marko Mikulicic 0:c0ecb8bf28eb 12831 }
Marko Mikulicic 0:c0ecb8bf28eb 12832 case OP_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 12833 case OP_NEW:
Marko Mikulicic 0:c0ecb8bf28eb 12834 p++;
Marko Mikulicic 0:c0ecb8bf28eb 12835 fprintf(f, "(%d)", *p);
Marko Mikulicic 0:c0ecb8bf28eb 12836 break;
Marko Mikulicic 0:c0ecb8bf28eb 12837 case OP_JMP:
Marko Mikulicic 0:c0ecb8bf28eb 12838 case OP_JMP_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 12839 case OP_JMP_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 12840 case OP_JMP_TRUE_DROP:
Marko Mikulicic 0:c0ecb8bf28eb 12841 case OP_JMP_IF_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 12842 case OP_TRY_PUSH_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 12843 case OP_TRY_PUSH_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 12844 case OP_TRY_PUSH_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 12845 case OP_TRY_PUSH_SWITCH: {
Marko Mikulicic 0:c0ecb8bf28eb 12846 bcode_off_t target;
Marko Mikulicic 0:c0ecb8bf28eb 12847 p++;
Marko Mikulicic 0:c0ecb8bf28eb 12848 memcpy(&target, p, sizeof(target));
Marko Mikulicic 0:c0ecb8bf28eb 12849 fprintf(f, "(%lu)", (unsigned long) target);
Marko Mikulicic 0:c0ecb8bf28eb 12850 p += sizeof(target) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 12851 break;
Marko Mikulicic 0:c0ecb8bf28eb 12852 }
Marko Mikulicic 0:c0ecb8bf28eb 12853 default:
Marko Mikulicic 0:c0ecb8bf28eb 12854 break;
Marko Mikulicic 0:c0ecb8bf28eb 12855 }
Marko Mikulicic 0:c0ecb8bf28eb 12856 fprintf(f, "\n");
Marko Mikulicic 0:c0ecb8bf28eb 12857 *ops = p;
Marko Mikulicic 0:c0ecb8bf28eb 12858 }
Marko Mikulicic 0:c0ecb8bf28eb 12859 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12860
Marko Mikulicic 0:c0ecb8bf28eb 12861 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 12862 V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12863 char *p = bcode_end_names(bcode->ops.p, bcode->names_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 12864 char *end = bcode->ops.p + bcode->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12865 for (; p < end; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 12866 dump_op(v7, f, bcode, &p);
Marko Mikulicic 0:c0ecb8bf28eb 12867 }
Marko Mikulicic 0:c0ecb8bf28eb 12868 }
Marko Mikulicic 0:c0ecb8bf28eb 12869 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12870
Marko Mikulicic 0:c0ecb8bf28eb 12871 V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode,
Marko Mikulicic 0:c0ecb8bf28eb 12872 void *filename, uint8_t filename_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12873 memset(bcode, 0x00, sizeof(*bcode));
Marko Mikulicic 0:c0ecb8bf28eb 12874 bcode->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12875 bcode->args_cnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12876 bcode->strict_mode = strict_mode;
Marko Mikulicic 0:c0ecb8bf28eb 12877 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12878 bcode->filename = filename;
Marko Mikulicic 0:c0ecb8bf28eb 12879 bcode->filename_in_rom = filename_in_rom;
Marko Mikulicic 0:c0ecb8bf28eb 12880 #else
Marko Mikulicic 0:c0ecb8bf28eb 12881 (void) filename;
Marko Mikulicic 0:c0ecb8bf28eb 12882 (void) filename_in_rom;
Marko Mikulicic 0:c0ecb8bf28eb 12883 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12884 }
Marko Mikulicic 0:c0ecb8bf28eb 12885
Marko Mikulicic 0:c0ecb8bf28eb 12886 V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12887 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12888 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12889 if (!bcode->ops_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12890 v7->bcode_ops_size -= bcode->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12891 }
Marko Mikulicic 0:c0ecb8bf28eb 12892
Marko Mikulicic 0:c0ecb8bf28eb 12893 v7->bcode_lit_total_size -= bcode->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12894 if (bcode->deserialized) {
Marko Mikulicic 0:c0ecb8bf28eb 12895 v7->bcode_lit_deser_size -= bcode->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12896 }
Marko Mikulicic 0:c0ecb8bf28eb 12897 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12898
Marko Mikulicic 0:c0ecb8bf28eb 12899 if (!bcode->ops_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12900 free(bcode->ops.p);
Marko Mikulicic 0:c0ecb8bf28eb 12901 }
Marko Mikulicic 0:c0ecb8bf28eb 12902 memset(&bcode->ops, 0x00, sizeof(bcode->ops));
Marko Mikulicic 0:c0ecb8bf28eb 12903
Marko Mikulicic 0:c0ecb8bf28eb 12904 free(bcode->lit.p);
Marko Mikulicic 0:c0ecb8bf28eb 12905 memset(&bcode->lit, 0x00, sizeof(bcode->lit));
Marko Mikulicic 0:c0ecb8bf28eb 12906
Marko Mikulicic 0:c0ecb8bf28eb 12907 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12908 if (!bcode->filename_in_rom && bcode->filename != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12909 shdata_release((struct shdata *) bcode->filename);
Marko Mikulicic 0:c0ecb8bf28eb 12910 bcode->filename = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 12911 }
Marko Mikulicic 0:c0ecb8bf28eb 12912 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12913
Marko Mikulicic 0:c0ecb8bf28eb 12914 bcode->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12915 }
Marko Mikulicic 0:c0ecb8bf28eb 12916
Marko Mikulicic 0:c0ecb8bf28eb 12917 V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *b) {
Marko Mikulicic 0:c0ecb8bf28eb 12918 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12919 if (!b->frozen) {
Marko Mikulicic 0:c0ecb8bf28eb 12920 b->refcnt++;
Marko Mikulicic 0:c0ecb8bf28eb 12921 }
Marko Mikulicic 0:c0ecb8bf28eb 12922 }
Marko Mikulicic 0:c0ecb8bf28eb 12923
Marko Mikulicic 0:c0ecb8bf28eb 12924 V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *b) {
Marko Mikulicic 0:c0ecb8bf28eb 12925 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12926 if (b->frozen) return;
Marko Mikulicic 0:c0ecb8bf28eb 12927
Marko Mikulicic 0:c0ecb8bf28eb 12928 assert(b->refcnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 12929 if (b->refcnt != 0) b->refcnt--;
Marko Mikulicic 0:c0ecb8bf28eb 12930
Marko Mikulicic 0:c0ecb8bf28eb 12931 if (b->refcnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 12932 bcode_free(v7, b);
Marko Mikulicic 0:c0ecb8bf28eb 12933 free(b);
Marko Mikulicic 0:c0ecb8bf28eb 12934 }
Marko Mikulicic 0:c0ecb8bf28eb 12935 }
Marko Mikulicic 0:c0ecb8bf28eb 12936
Marko Mikulicic 0:c0ecb8bf28eb 12937 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12938 V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12939 const char *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 12940 if (bcode->filename_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12941 ret = (const char *) bcode->filename;
Marko Mikulicic 0:c0ecb8bf28eb 12942 } else if (bcode->filename != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12943 ret = (const char *) shdata_get_payload((struct shdata *) bcode->filename);
Marko Mikulicic 0:c0ecb8bf28eb 12944 }
Marko Mikulicic 0:c0ecb8bf28eb 12945 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12946 }
Marko Mikulicic 0:c0ecb8bf28eb 12947 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12948
Marko Mikulicic 0:c0ecb8bf28eb 12949 V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src) {
Marko Mikulicic 0:c0ecb8bf28eb 12950 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12951 dst->filename_in_rom = src->filename_in_rom;
Marko Mikulicic 0:c0ecb8bf28eb 12952 dst->filename = src->filename;
Marko Mikulicic 0:c0ecb8bf28eb 12953
Marko Mikulicic 0:c0ecb8bf28eb 12954 if (src->filename != NULL && !src->filename_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12955 shdata_retain((struct shdata *) dst->filename);
Marko Mikulicic 0:c0ecb8bf28eb 12956 }
Marko Mikulicic 0:c0ecb8bf28eb 12957 #else
Marko Mikulicic 0:c0ecb8bf28eb 12958 (void) dst;
Marko Mikulicic 0:c0ecb8bf28eb 12959 (void) src;
Marko Mikulicic 0:c0ecb8bf28eb 12960 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12961 }
Marko Mikulicic 0:c0ecb8bf28eb 12962
Marko Mikulicic 0:c0ecb8bf28eb 12963 V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op) {
Marko Mikulicic 0:c0ecb8bf28eb 12964 bcode_ops_append(bbuilder, &op, 1);
Marko Mikulicic 0:c0ecb8bf28eb 12965 }
Marko Mikulicic 0:c0ecb8bf28eb 12966
Marko Mikulicic 0:c0ecb8bf28eb 12967 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 12968 V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 12969 int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 12970 int offset = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12971 bcode_add_varint(bbuilder, (line_no << 1) | 1);
Marko Mikulicic 0:c0ecb8bf28eb 12972 bbuilder->ops.buf[offset] = msb_lsb_swap(bbuilder->ops.buf[offset]);
Marko Mikulicic 0:c0ecb8bf28eb 12973 assert(bbuilder->ops.buf[offset] & _OP_LINE_NO);
Marko Mikulicic 0:c0ecb8bf28eb 12974 }
Marko Mikulicic 0:c0ecb8bf28eb 12975 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12976
Marko Mikulicic 0:c0ecb8bf28eb 12977 /*
Marko Mikulicic 0:c0ecb8bf28eb 12978 * Appends varint-encoded integer to the `ops` mbuf
Marko Mikulicic 0:c0ecb8bf28eb 12979 */
Marko Mikulicic 0:c0ecb8bf28eb 12980 V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value) {
Marko Mikulicic 0:c0ecb8bf28eb 12981 int k = calc_llen(value); /* Calculate how many bytes length takes */
Marko Mikulicic 0:c0ecb8bf28eb 12982 int offset = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12983
Marko Mikulicic 0:c0ecb8bf28eb 12984 /* Allocate buffer */
Marko Mikulicic 0:c0ecb8bf28eb 12985 bcode_ops_append(bbuilder, NULL, k);
Marko Mikulicic 0:c0ecb8bf28eb 12986
Marko Mikulicic 0:c0ecb8bf28eb 12987 /* Write value */
Marko Mikulicic 0:c0ecb8bf28eb 12988 encode_varint(value, (unsigned char *) bbuilder->ops.buf + offset);
Marko Mikulicic 0:c0ecb8bf28eb 12989 }
Marko Mikulicic 0:c0ecb8bf28eb 12990
Marko Mikulicic 0:c0ecb8bf28eb 12991 V7_PRIVATE size_t bcode_get_varint(char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 12992 size_t ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12993 int len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12994 (*ops)++;
Marko Mikulicic 0:c0ecb8bf28eb 12995 ret = decode_varint((unsigned char *) *ops, &len);
Marko Mikulicic 0:c0ecb8bf28eb 12996 *ops += len - 1;
Marko Mikulicic 0:c0ecb8bf28eb 12997 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12998 }
Marko Mikulicic 0:c0ecb8bf28eb 12999
Marko Mikulicic 0:c0ecb8bf28eb 13000 static int bcode_is_inline_string(struct v7 *v7, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 13001 uint64_t tag = val & V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 13002 if (v7->is_precompiling && v7_is_string(val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13003 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 13004 }
Marko Mikulicic 0:c0ecb8bf28eb 13005 return tag == V7_TAG_STRING_I || tag == V7_TAG_STRING_5;
Marko Mikulicic 0:c0ecb8bf28eb 13006 }
Marko Mikulicic 0:c0ecb8bf28eb 13007
Marko Mikulicic 0:c0ecb8bf28eb 13008 static int bcode_is_inline_func(struct v7 *v7, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 13009 return (v7->is_precompiling && is_js_function(val));
Marko Mikulicic 0:c0ecb8bf28eb 13010 }
Marko Mikulicic 0:c0ecb8bf28eb 13011
Marko Mikulicic 0:c0ecb8bf28eb 13012 static int bcode_is_inline_regexp(struct v7 *v7, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 13013 return (v7->is_precompiling && v7_is_regexp(v7, val));
Marko Mikulicic 0:c0ecb8bf28eb 13014 }
Marko Mikulicic 0:c0ecb8bf28eb 13015
Marko Mikulicic 0:c0ecb8bf28eb 13016 V7_PRIVATE lit_t bcode_add_lit(struct bcode_builder *bbuilder, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 13017 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 13018 memset(&lit, 0, sizeof(lit));
Marko Mikulicic 0:c0ecb8bf28eb 13019
Marko Mikulicic 0:c0ecb8bf28eb 13020 if (bcode_is_inline_string(bbuilder->v7, val) ||
Marko Mikulicic 0:c0ecb8bf28eb 13021 bcode_is_inline_func(bbuilder->v7, val) || v7_is_number(val) ||
Marko Mikulicic 0:c0ecb8bf28eb 13022 bcode_is_inline_regexp(bbuilder->v7, val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13023 /* literal should be inlined (it's `bcode_op_lit()` who does this) */
Marko Mikulicic 0:c0ecb8bf28eb 13024 lit.mode = LIT_MODE__INLINED;
Marko Mikulicic 0:c0ecb8bf28eb 13025 lit.v.inline_val = val;
Marko Mikulicic 0:c0ecb8bf28eb 13026 } else {
Marko Mikulicic 0:c0ecb8bf28eb 13027 /* literal will now be added to the literal table */
Marko Mikulicic 0:c0ecb8bf28eb 13028 lit.mode = LIT_MODE__TABLE;
Marko Mikulicic 0:c0ecb8bf28eb 13029 lit.v.lit_idx = bbuilder->lit.len / sizeof(val);
Marko Mikulicic 0:c0ecb8bf28eb 13030
Marko Mikulicic 0:c0ecb8bf28eb 13031 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 13032 bbuilder->v7->bcode_lit_total_size -= bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 13033 if (bbuilder->bcode->deserialized) {
Marko Mikulicic 0:c0ecb8bf28eb 13034 bbuilder->v7->bcode_lit_deser_size -= bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 13035 }
Marko Mikulicic 0:c0ecb8bf28eb 13036 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13037
Marko Mikulicic 0:c0ecb8bf28eb 13038 mbuf_append(&bbuilder->lit, &val, sizeof(val));
Marko Mikulicic 0:c0ecb8bf28eb 13039
Marko Mikulicic 0:c0ecb8bf28eb 13040 /*
Marko Mikulicic 0:c0ecb8bf28eb 13041 * immediately propagate current lit buffer to the bcode, so that GC will
Marko Mikulicic 0:c0ecb8bf28eb 13042 * be aware of it
Marko Mikulicic 0:c0ecb8bf28eb 13043 */
Marko Mikulicic 0:c0ecb8bf28eb 13044 bbuilder->bcode->lit.p = bbuilder->lit.buf;
Marko Mikulicic 0:c0ecb8bf28eb 13045 bbuilder->bcode->lit.len = bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 13046
Marko Mikulicic 0:c0ecb8bf28eb 13047 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 13048 bbuilder->v7->bcode_lit_total_size += bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 13049 if (bbuilder->bcode->deserialized) {
Marko Mikulicic 0:c0ecb8bf28eb 13050 bbuilder->v7->bcode_lit_deser_size += bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 13051 }
Marko Mikulicic 0:c0ecb8bf28eb 13052 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13053 }
Marko Mikulicic 0:c0ecb8bf28eb 13054 return lit;
Marko Mikulicic 0:c0ecb8bf28eb 13055 }
Marko Mikulicic 0:c0ecb8bf28eb 13056
Marko Mikulicic 0:c0ecb8bf28eb 13057 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 13058 V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13059 val_t ret;
Marko Mikulicic 0:c0ecb8bf28eb 13060 memcpy(&ret, bcode->lit.p + (size_t) idx * sizeof(ret), sizeof(ret));
Marko Mikulicic 0:c0ecb8bf28eb 13061 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 13062 }
Marko Mikulicic 0:c0ecb8bf28eb 13063 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13064
Marko Mikulicic 0:c0ecb8bf28eb 13065 static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13066 const char *data);
Marko Mikulicic 0:c0ecb8bf28eb 13067
Marko Mikulicic 0:c0ecb8bf28eb 13068 V7_PRIVATE v7_val_t
Marko Mikulicic 0:c0ecb8bf28eb 13069 bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 13070 struct v7_vec *vec = &bcode->lit;
Marko Mikulicic 0:c0ecb8bf28eb 13071 size_t idx = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13072 switch (idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13073 case BCODE_INLINE_STRING_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13074 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 13075 size_t len = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13076 res = v7_mk_string(
Marko Mikulicic 0:c0ecb8bf28eb 13077 v7, (const char *) *ops + 1 /*skip BCODE_INLINE_STRING_TYPE_TAG*/,
Marko Mikulicic 0:c0ecb8bf28eb 13078 len, !bcode->ops_in_rom);
Marko Mikulicic 0:c0ecb8bf28eb 13079 *ops += len + 1;
Marko Mikulicic 0:c0ecb8bf28eb 13080 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13081 }
Marko Mikulicic 0:c0ecb8bf28eb 13082 case BCODE_INLINE_NUMBER_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13083 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 13084 memcpy(&res, *ops + 1 /*skip BCODE_INLINE_NUMBER_TYPE_TAG*/, sizeof(res));
Marko Mikulicic 0:c0ecb8bf28eb 13085 *ops += sizeof(res);
Marko Mikulicic 0:c0ecb8bf28eb 13086 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13087 }
Marko Mikulicic 0:c0ecb8bf28eb 13088 case BCODE_INLINE_FUNC_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13089 /*
Marko Mikulicic 0:c0ecb8bf28eb 13090 * Create half-done function: without scope but _with_ prototype. Scope
Marko Mikulicic 0:c0ecb8bf28eb 13091 * will be set by `bcode_instantiate_function()`.
Marko Mikulicic 0:c0ecb8bf28eb 13092 *
Marko Mikulicic 0:c0ecb8bf28eb 13093 * The fact that the prototype is already set will make
Marko Mikulicic 0:c0ecb8bf28eb 13094 * `bcode_instantiate_function()` just set scope on this function,
Marko Mikulicic 0:c0ecb8bf28eb 13095 * instead of creating a new one.
Marko Mikulicic 0:c0ecb8bf28eb 13096 */
Marko Mikulicic 0:c0ecb8bf28eb 13097 val_t res = mk_js_function(v7, NULL, v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 13098
Marko Mikulicic 0:c0ecb8bf28eb 13099 /* Create bcode in this half-done function */
Marko Mikulicic 0:c0ecb8bf28eb 13100 struct v7_js_function *func = get_js_function_struct(res);
Marko Mikulicic 0:c0ecb8bf28eb 13101
Marko Mikulicic 0:c0ecb8bf28eb 13102 func->bcode = (struct bcode *) calloc(1, sizeof(*func->bcode));
Marko Mikulicic 0:c0ecb8bf28eb 13103 bcode_init(func->bcode, bcode->strict_mode, NULL /* will be set below */,
Marko Mikulicic 0:c0ecb8bf28eb 13104 0);
Marko Mikulicic 0:c0ecb8bf28eb 13105 bcode_copy_filename_from(func->bcode, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 13106 retain_bcode(v7, func->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 13107
Marko Mikulicic 0:c0ecb8bf28eb 13108 /* deserialize the function's bcode from `ops` */
Marko Mikulicic 0:c0ecb8bf28eb 13109 *ops = (char *) bcode_deserialize_func(
Marko Mikulicic 0:c0ecb8bf28eb 13110 v7, func->bcode, *ops + 1 /*skip BCODE_INLINE_FUNC_TYPE_TAG*/);
Marko Mikulicic 0:c0ecb8bf28eb 13111
Marko Mikulicic 0:c0ecb8bf28eb 13112 /* decrement *ops, because it will be incremented by `eval_bcode` soon */
Marko Mikulicic 0:c0ecb8bf28eb 13113 *ops -= 1;
Marko Mikulicic 0:c0ecb8bf28eb 13114
Marko Mikulicic 0:c0ecb8bf28eb 13115 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13116 }
Marko Mikulicic 0:c0ecb8bf28eb 13117 case BCODE_INLINE_REGEXP_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13118 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 13119 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 13120 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 13121 size_t len_src, len_flags;
Marko Mikulicic 0:c0ecb8bf28eb 13122 char *buf_src, *buf_flags;
Marko Mikulicic 0:c0ecb8bf28eb 13123
Marko Mikulicic 0:c0ecb8bf28eb 13124 len_src = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13125 buf_src = *ops + 1;
Marko Mikulicic 0:c0ecb8bf28eb 13126 *ops += len_src + 1 /* nul term */;
Marko Mikulicic 0:c0ecb8bf28eb 13127
Marko Mikulicic 0:c0ecb8bf28eb 13128 len_flags = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13129 buf_flags = *ops + 1;
Marko Mikulicic 0:c0ecb8bf28eb 13130 *ops += len_flags + 1 /* nul term */;
Marko Mikulicic 0:c0ecb8bf28eb 13131
Marko Mikulicic 0:c0ecb8bf28eb 13132 rcode = v7_mk_regexp(v7, buf_src, len_src, buf_flags, len_flags, &res);
Marko Mikulicic 0:c0ecb8bf28eb 13133 assert(rcode == V7_OK);
Marko Mikulicic 0:c0ecb8bf28eb 13134 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 13135
Marko Mikulicic 0:c0ecb8bf28eb 13136 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13137 #else
Marko Mikulicic 0:c0ecb8bf28eb 13138 fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n");
Marko Mikulicic 0:c0ecb8bf28eb 13139 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13140 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13141 }
Marko Mikulicic 0:c0ecb8bf28eb 13142 default:
Marko Mikulicic 0:c0ecb8bf28eb 13143 return ((val_t *) vec->p)[idx - BCODE_MAX_INLINE_TYPE_TAG];
Marko Mikulicic 0:c0ecb8bf28eb 13144 }
Marko Mikulicic 0:c0ecb8bf28eb 13145 }
Marko Mikulicic 0:c0ecb8bf28eb 13146
Marko Mikulicic 0:c0ecb8bf28eb 13147 V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op,
Marko Mikulicic 0:c0ecb8bf28eb 13148 lit_t lit) {
Marko Mikulicic 0:c0ecb8bf28eb 13149 bcode_op(bbuilder, op);
Marko Mikulicic 0:c0ecb8bf28eb 13150
Marko Mikulicic 0:c0ecb8bf28eb 13151 switch (lit.mode) {
Marko Mikulicic 0:c0ecb8bf28eb 13152 case LIT_MODE__TABLE:
Marko Mikulicic 0:c0ecb8bf28eb 13153 bcode_add_varint(bbuilder, lit.v.lit_idx + BCODE_MAX_INLINE_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13154 break;
Marko Mikulicic 0:c0ecb8bf28eb 13155
Marko Mikulicic 0:c0ecb8bf28eb 13156 case LIT_MODE__INLINED:
Marko Mikulicic 0:c0ecb8bf28eb 13157 if (v7_is_string(lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13158 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13159 const char *s = v7_get_string(bbuilder->v7, &lit.v.inline_val, &len);
Marko Mikulicic 0:c0ecb8bf28eb 13160 bcode_add_varint(bbuilder, BCODE_INLINE_STRING_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13161 bcode_add_varint(bbuilder, len);
Marko Mikulicic 0:c0ecb8bf28eb 13162 bcode_ops_append(bbuilder, s, len + 1 /* nul term */);
Marko Mikulicic 0:c0ecb8bf28eb 13163 } else if (v7_is_number(lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13164 bcode_add_varint(bbuilder, BCODE_INLINE_NUMBER_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13165 /*
Marko Mikulicic 0:c0ecb8bf28eb 13166 * TODO(dfrank): we can save some memory by storing string
Marko Mikulicic 0:c0ecb8bf28eb 13167 * representation of a number here, instead of wasting 8 bytes for each
Marko Mikulicic 0:c0ecb8bf28eb 13168 * number.
Marko Mikulicic 0:c0ecb8bf28eb 13169 *
Marko Mikulicic 0:c0ecb8bf28eb 13170 * Alternatively, we can add more tags for integers, like
Marko Mikulicic 0:c0ecb8bf28eb 13171 * `BCODE_INLINE_S08_TYPE_TAG`, `BCODE_INLINE_S16_TYPE_TAG`, etc, since
Marko Mikulicic 0:c0ecb8bf28eb 13172 * integers are the most common numbers for sure.
Marko Mikulicic 0:c0ecb8bf28eb 13173 */
Marko Mikulicic 0:c0ecb8bf28eb 13174 bcode_ops_append(bbuilder, &lit.v.inline_val, sizeof(lit.v.inline_val));
Marko Mikulicic 0:c0ecb8bf28eb 13175 } else if (is_js_function(lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13176 /*
Marko Mikulicic 0:c0ecb8bf28eb 13177 * TODO(dfrank): implement `bcode_serialize_*` more generically, so
Marko Mikulicic 0:c0ecb8bf28eb 13178 * that they can write to buffer instead of a `FILE`. Then, remove this
Marko Mikulicic 0:c0ecb8bf28eb 13179 * workaround with `CS_PLATFORM == CS_P_UNIX`, `tmpfile()`, etc.
Marko Mikulicic 0:c0ecb8bf28eb 13180 */
Marko Mikulicic 0:c0ecb8bf28eb 13181 #if CS_PLATFORM == CS_P_UNIX
Marko Mikulicic 0:c0ecb8bf28eb 13182 struct v7_js_function *func;
Marko Mikulicic 0:c0ecb8bf28eb 13183 FILE *fp = tmpfile();
Marko Mikulicic 0:c0ecb8bf28eb 13184 long len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13185 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 13186
Marko Mikulicic 0:c0ecb8bf28eb 13187 func = get_js_function_struct(lit.v.inline_val);
Marko Mikulicic 0:c0ecb8bf28eb 13188
Marko Mikulicic 0:c0ecb8bf28eb 13189 /* we inline functions if only we're precompiling */
Marko Mikulicic 0:c0ecb8bf28eb 13190 assert(bbuilder->v7->is_precompiling);
Marko Mikulicic 0:c0ecb8bf28eb 13191
Marko Mikulicic 0:c0ecb8bf28eb 13192 bcode_add_varint(bbuilder, BCODE_INLINE_FUNC_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13193 bcode_serialize_func(bbuilder->v7, func->bcode, fp);
Marko Mikulicic 0:c0ecb8bf28eb 13194
Marko Mikulicic 0:c0ecb8bf28eb 13195 fflush(fp);
Marko Mikulicic 0:c0ecb8bf28eb 13196
Marko Mikulicic 0:c0ecb8bf28eb 13197 len = ftell(fp);
Marko Mikulicic 0:c0ecb8bf28eb 13198
Marko Mikulicic 0:c0ecb8bf28eb 13199 p = (char *) mmap(NULL, len, PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
Marko Mikulicic 0:c0ecb8bf28eb 13200
Marko Mikulicic 0:c0ecb8bf28eb 13201 bcode_ops_append(bbuilder, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 13202
Marko Mikulicic 0:c0ecb8bf28eb 13203 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 13204 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13205 } else if (v7_is_regexp(bbuilder->v7, lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13206 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 13207 struct v7_regexp *rp =
Marko Mikulicic 0:c0ecb8bf28eb 13208 v7_get_regexp_struct(bbuilder->v7, lit.v.inline_val);
Marko Mikulicic 0:c0ecb8bf28eb 13209 bcode_add_varint(bbuilder, BCODE_INLINE_REGEXP_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13210
Marko Mikulicic 0:c0ecb8bf28eb 13211 /* append regexp source */
Marko Mikulicic 0:c0ecb8bf28eb 13212 {
Marko Mikulicic 0:c0ecb8bf28eb 13213 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13214 const char *buf =
Marko Mikulicic 0:c0ecb8bf28eb 13215 v7_get_string(bbuilder->v7, &rp->regexp_string, &len);
Marko Mikulicic 0:c0ecb8bf28eb 13216 bcode_add_varint(bbuilder, len);
Marko Mikulicic 0:c0ecb8bf28eb 13217 bcode_ops_append(bbuilder, buf, len + 1 /* nul term */);
Marko Mikulicic 0:c0ecb8bf28eb 13218 }
Marko Mikulicic 0:c0ecb8bf28eb 13219
Marko Mikulicic 0:c0ecb8bf28eb 13220 /* append regexp flags */
Marko Mikulicic 0:c0ecb8bf28eb 13221 {
Marko Mikulicic 0:c0ecb8bf28eb 13222 char buf[_V7_REGEXP_MAX_FLAGS_LEN + 1 /* nul term */];
Marko Mikulicic 0:c0ecb8bf28eb 13223 size_t len = get_regexp_flags_str(bbuilder->v7, rp, buf);
Marko Mikulicic 0:c0ecb8bf28eb 13224 bcode_add_varint(bbuilder, len);
Marko Mikulicic 0:c0ecb8bf28eb 13225 bcode_ops_append(bbuilder, buf, len + 1 /* nul term */);
Marko Mikulicic 0:c0ecb8bf28eb 13226 }
Marko Mikulicic 0:c0ecb8bf28eb 13227 #else
Marko Mikulicic 0:c0ecb8bf28eb 13228 fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n");
Marko Mikulicic 0:c0ecb8bf28eb 13229 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13230 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13231 } else {
Marko Mikulicic 0:c0ecb8bf28eb 13232 /* invalid type of inlined value */
Marko Mikulicic 0:c0ecb8bf28eb 13233 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13234 }
Marko Mikulicic 0:c0ecb8bf28eb 13235 break;
Marko Mikulicic 0:c0ecb8bf28eb 13236
Marko Mikulicic 0:c0ecb8bf28eb 13237 default:
Marko Mikulicic 0:c0ecb8bf28eb 13238 /* invalid literal mode */
Marko Mikulicic 0:c0ecb8bf28eb 13239 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13240 break;
Marko Mikulicic 0:c0ecb8bf28eb 13241 }
Marko Mikulicic 0:c0ecb8bf28eb 13242 }
Marko Mikulicic 0:c0ecb8bf28eb 13243
Marko Mikulicic 0:c0ecb8bf28eb 13244 V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit) {
Marko Mikulicic 0:c0ecb8bf28eb 13245 bcode_op_lit(bbuilder, OP_PUSH_LIT, lit);
Marko Mikulicic 0:c0ecb8bf28eb 13246 }
Marko Mikulicic 0:c0ecb8bf28eb 13247
Marko Mikulicic 0:c0ecb8bf28eb 13248 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 13249 /*V7_PRIVATE*/ enum v7_err
Marko Mikulicic 0:c0ecb8bf28eb 13250 bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 13251 size_t *idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13252 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 13253 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 13254 size_t ops_index;
Marko Mikulicic 0:c0ecb8bf28eb 13255
Marko Mikulicic 0:c0ecb8bf28eb 13256 /*
Marko Mikulicic 0:c0ecb8bf28eb 13257 * if name length is not provided, assume it's null-terminated and calculate
Marko Mikulicic 0:c0ecb8bf28eb 13258 * it
Marko Mikulicic 0:c0ecb8bf28eb 13259 */
Marko Mikulicic 0:c0ecb8bf28eb 13260 if (len == ~((size_t) 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 13261 len = strlen(p);
Marko Mikulicic 0:c0ecb8bf28eb 13262 }
Marko Mikulicic 0:c0ecb8bf28eb 13263
Marko Mikulicic 0:c0ecb8bf28eb 13264 /* index at which to put name. If not provided, we'll append at the end */
Marko Mikulicic 0:c0ecb8bf28eb 13265 if (idx != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13266 ops_index = *idx;
Marko Mikulicic 0:c0ecb8bf28eb 13267 } else {
Marko Mikulicic 0:c0ecb8bf28eb 13268 ops_index = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 13269 }
Marko Mikulicic 0:c0ecb8bf28eb 13270
Marko Mikulicic 0:c0ecb8bf28eb 13271 /* calculate how much varint len will take */
Marko Mikulicic 0:c0ecb8bf28eb 13272 llen = calc_llen(len);
Marko Mikulicic 0:c0ecb8bf28eb 13273
Marko Mikulicic 0:c0ecb8bf28eb 13274 /* reserve space in `ops` buffer */
Marko Mikulicic 0:c0ecb8bf28eb 13275 mbuf_insert(&bbuilder->ops, ops_index, NULL, llen + len + 1 /*null-term*/);
Marko Mikulicic 0:c0ecb8bf28eb 13276
Marko Mikulicic 0:c0ecb8bf28eb 13277 {
Marko Mikulicic 0:c0ecb8bf28eb 13278 char *ops = bbuilder->ops.buf + ops_index;
Marko Mikulicic 0:c0ecb8bf28eb 13279
Marko Mikulicic 0:c0ecb8bf28eb 13280 /* put varint len */
Marko Mikulicic 0:c0ecb8bf28eb 13281 ops += encode_varint(len, (unsigned char *) ops);
Marko Mikulicic 0:c0ecb8bf28eb 13282
Marko Mikulicic 0:c0ecb8bf28eb 13283 /* put string */
Marko Mikulicic 0:c0ecb8bf28eb 13284 memcpy(ops, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 13285 ops += len;
Marko Mikulicic 0:c0ecb8bf28eb 13286
Marko Mikulicic 0:c0ecb8bf28eb 13287 /* null-terminate */
Marko Mikulicic 0:c0ecb8bf28eb 13288 *ops++ = 0x00;
Marko Mikulicic 0:c0ecb8bf28eb 13289
Marko Mikulicic 0:c0ecb8bf28eb 13290 if (idx != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13291 *idx = ops - bbuilder->ops.buf;
Marko Mikulicic 0:c0ecb8bf28eb 13292 }
Marko Mikulicic 0:c0ecb8bf28eb 13293 }
Marko Mikulicic 0:c0ecb8bf28eb 13294
Marko Mikulicic 0:c0ecb8bf28eb 13295 /* maintain total number of names */
Marko Mikulicic 0:c0ecb8bf28eb 13296 if (bbuilder->bcode->names_cnt < V7_NAMES_CNT_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 13297 bbuilder->bcode->names_cnt++;
Marko Mikulicic 0:c0ecb8bf28eb 13298 } else {
Marko Mikulicic 0:c0ecb8bf28eb 13299 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Too many local variables");
Marko Mikulicic 0:c0ecb8bf28eb 13300 }
Marko Mikulicic 0:c0ecb8bf28eb 13301
Marko Mikulicic 0:c0ecb8bf28eb 13302 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 13303 }
Marko Mikulicic 0:c0ecb8bf28eb 13304
Marko Mikulicic 0:c0ecb8bf28eb 13305 /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt) {
Marko Mikulicic 0:c0ecb8bf28eb 13306 while (names_cnt--) {
Marko Mikulicic 0:c0ecb8bf28eb 13307 ops = bcode_next_name(ops, NULL, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 13308 }
Marko Mikulicic 0:c0ecb8bf28eb 13309 return ops;
Marko Mikulicic 0:c0ecb8bf28eb 13310 }
Marko Mikulicic 0:c0ecb8bf28eb 13311
Marko Mikulicic 0:c0ecb8bf28eb 13312 V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen) {
Marko Mikulicic 0:c0ecb8bf28eb 13313 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13314 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 13315
Marko Mikulicic 0:c0ecb8bf28eb 13316 len = decode_varint((unsigned char *) ops, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 13317
Marko Mikulicic 0:c0ecb8bf28eb 13318 ops += llen;
Marko Mikulicic 0:c0ecb8bf28eb 13319
Marko Mikulicic 0:c0ecb8bf28eb 13320 if (pname != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13321 *pname = ops;
Marko Mikulicic 0:c0ecb8bf28eb 13322 }
Marko Mikulicic 0:c0ecb8bf28eb 13323
Marko Mikulicic 0:c0ecb8bf28eb 13324 if (plen != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13325 *plen = len;
Marko Mikulicic 0:c0ecb8bf28eb 13326 }
Marko Mikulicic 0:c0ecb8bf28eb 13327
Marko Mikulicic 0:c0ecb8bf28eb 13328 ops += len + 1 /*null-terminator*/;
Marko Mikulicic 0:c0ecb8bf28eb 13329 return ops;
Marko Mikulicic 0:c0ecb8bf28eb 13330 }
Marko Mikulicic 0:c0ecb8bf28eb 13331
Marko Mikulicic 0:c0ecb8bf28eb 13332 V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13333 char *ops, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 13334 char *name;
Marko Mikulicic 0:c0ecb8bf28eb 13335 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13336
Marko Mikulicic 0:c0ecb8bf28eb 13337 ops = bcode_next_name(ops, &name, &len);
Marko Mikulicic 0:c0ecb8bf28eb 13338
Marko Mikulicic 0:c0ecb8bf28eb 13339 /*
Marko Mikulicic 0:c0ecb8bf28eb 13340 * If `ops` is in RAM, we create owned string, since the string may outlive
Marko Mikulicic 0:c0ecb8bf28eb 13341 * bcode. Otherwise (`ops` is in ROM), we create foreign string.
Marko Mikulicic 0:c0ecb8bf28eb 13342 */
Marko Mikulicic 0:c0ecb8bf28eb 13343 *res = v7_mk_string(v7, name, len, !bcode->ops_in_rom);
Marko Mikulicic 0:c0ecb8bf28eb 13344
Marko Mikulicic 0:c0ecb8bf28eb 13345 return ops;
Marko Mikulicic 0:c0ecb8bf28eb 13346 }
Marko Mikulicic 0:c0ecb8bf28eb 13347
Marko Mikulicic 0:c0ecb8bf28eb 13348 V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder) {
Marko Mikulicic 0:c0ecb8bf28eb 13349 return bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 13350 }
Marko Mikulicic 0:c0ecb8bf28eb 13351
Marko Mikulicic 0:c0ecb8bf28eb 13352 /*
Marko Mikulicic 0:c0ecb8bf28eb 13353 * Appends a branch target and returns its location.
Marko Mikulicic 0:c0ecb8bf28eb 13354 * This location can be updated with bcode_patch_target.
Marko Mikulicic 0:c0ecb8bf28eb 13355 * To be issued following a JMP_* bytecode
Marko Mikulicic 0:c0ecb8bf28eb 13356 */
Marko Mikulicic 0:c0ecb8bf28eb 13357 V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder) {
Marko Mikulicic 0:c0ecb8bf28eb 13358 bcode_off_t pos = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 13359 bcode_off_t zero = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13360 bcode_ops_append(bbuilder, &zero, sizeof(bcode_off_t));
Marko Mikulicic 0:c0ecb8bf28eb 13361 return pos;
Marko Mikulicic 0:c0ecb8bf28eb 13362 }
Marko Mikulicic 0:c0ecb8bf28eb 13363
Marko Mikulicic 0:c0ecb8bf28eb 13364 /*
Marko Mikulicic 0:c0ecb8bf28eb 13365 * Appends an op requiring a branch target. See bcode_add_target.
Marko Mikulicic 0:c0ecb8bf28eb 13366 *
Marko Mikulicic 0:c0ecb8bf28eb 13367 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 13368 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 13369 */
Marko Mikulicic 0:c0ecb8bf28eb 13370 /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 13371 uint8_t op) {
Marko Mikulicic 0:c0ecb8bf28eb 13372 bcode_op(bbuilder, op);
Marko Mikulicic 0:c0ecb8bf28eb 13373 return bcode_add_target(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 13374 }
Marko Mikulicic 0:c0ecb8bf28eb 13375
Marko Mikulicic 0:c0ecb8bf28eb 13376 /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 13377 bcode_off_t label, bcode_off_t target) {
Marko Mikulicic 0:c0ecb8bf28eb 13378 memcpy(bbuilder->ops.buf + label, &target, sizeof(target));
Marko Mikulicic 0:c0ecb8bf28eb 13379 }
Marko Mikulicic 0:c0ecb8bf28eb 13380
Marko Mikulicic 0:c0ecb8bf28eb 13381 /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13382 FILE *out) {
Marko Mikulicic 0:c0ecb8bf28eb 13383 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 13384 (void) bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13385
Marko Mikulicic 0:c0ecb8bf28eb 13386 fwrite(BIN_BCODE_SIGNATURE, sizeof(BIN_BCODE_SIGNATURE), 1, out);
Marko Mikulicic 0:c0ecb8bf28eb 13387 bcode_serialize_func(v7, bcode, out);
Marko Mikulicic 0:c0ecb8bf28eb 13388 }
Marko Mikulicic 0:c0ecb8bf28eb 13389
Marko Mikulicic 0:c0ecb8bf28eb 13390 static void bcode_serialize_varint(int n, FILE *out) {
Marko Mikulicic 0:c0ecb8bf28eb 13391 unsigned char buf[8];
Marko Mikulicic 0:c0ecb8bf28eb 13392 int k = calc_llen(n);
Marko Mikulicic 0:c0ecb8bf28eb 13393 encode_varint(n, buf);
Marko Mikulicic 0:c0ecb8bf28eb 13394 fwrite(buf, k, 1, out);
Marko Mikulicic 0:c0ecb8bf28eb 13395 }
Marko Mikulicic 0:c0ecb8bf28eb 13396
Marko Mikulicic 0:c0ecb8bf28eb 13397 static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13398 FILE *out) {
Marko Mikulicic 0:c0ecb8bf28eb 13399 struct v7_vec *vec;
Marko Mikulicic 0:c0ecb8bf28eb 13400 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 13401
Marko Mikulicic 0:c0ecb8bf28eb 13402 /*
Marko Mikulicic 0:c0ecb8bf28eb 13403 * All literals should be inlined into `ops`, so we expect literals table
Marko Mikulicic 0:c0ecb8bf28eb 13404 * to be empty here
Marko Mikulicic 0:c0ecb8bf28eb 13405 */
Marko Mikulicic 0:c0ecb8bf28eb 13406 assert(bcode->lit.len == 0);
Marko Mikulicic 0:c0ecb8bf28eb 13407
Marko Mikulicic 0:c0ecb8bf28eb 13408 /* args_cnt */
Marko Mikulicic 0:c0ecb8bf28eb 13409 bcode_serialize_varint(bcode->args_cnt, out);
Marko Mikulicic 0:c0ecb8bf28eb 13410
Marko Mikulicic 0:c0ecb8bf28eb 13411 /* names_cnt */
Marko Mikulicic 0:c0ecb8bf28eb 13412 bcode_serialize_varint(bcode->names_cnt, out);
Marko Mikulicic 0:c0ecb8bf28eb 13413
Marko Mikulicic 0:c0ecb8bf28eb 13414 /* func_name_present */
Marko Mikulicic 0:c0ecb8bf28eb 13415 bcode_serialize_varint(bcode->func_name_present, out);
Marko Mikulicic 0:c0ecb8bf28eb 13416
Marko Mikulicic 0:c0ecb8bf28eb 13417 /*
Marko Mikulicic 0:c0ecb8bf28eb 13418 * bcode:
Marko Mikulicic 0:c0ecb8bf28eb 13419 * <varint> // opcodes length
Marko Mikulicic 0:c0ecb8bf28eb 13420 * <opcode>*
Marko Mikulicic 0:c0ecb8bf28eb 13421 */
Marko Mikulicic 0:c0ecb8bf28eb 13422 vec = &bcode->ops;
Marko Mikulicic 0:c0ecb8bf28eb 13423 bcode_serialize_varint(vec->len, out);
Marko Mikulicic 0:c0ecb8bf28eb 13424 fwrite(vec->p, vec->len, 1, out);
Marko Mikulicic 0:c0ecb8bf28eb 13425 }
Marko Mikulicic 0:c0ecb8bf28eb 13426
Marko Mikulicic 0:c0ecb8bf28eb 13427 static size_t bcode_deserialize_varint(const char **data) {
Marko Mikulicic 0:c0ecb8bf28eb 13428 size_t ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13429 int len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13430 ret = decode_varint((const unsigned char *) (*data), &len);
Marko Mikulicic 0:c0ecb8bf28eb 13431 *data += len;
Marko Mikulicic 0:c0ecb8bf28eb 13432 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 13433 }
Marko Mikulicic 0:c0ecb8bf28eb 13434
Marko Mikulicic 0:c0ecb8bf28eb 13435 static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13436 const char *data) {
Marko Mikulicic 0:c0ecb8bf28eb 13437 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 13438 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 13439
Marko Mikulicic 0:c0ecb8bf28eb 13440 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 13441
Marko Mikulicic 0:c0ecb8bf28eb 13442 /*
Marko Mikulicic 0:c0ecb8bf28eb 13443 * before deserializing, set the corresponding flag, so that metrics will be
Marko Mikulicic 0:c0ecb8bf28eb 13444 * updated accordingly
Marko Mikulicic 0:c0ecb8bf28eb 13445 */
Marko Mikulicic 0:c0ecb8bf28eb 13446 bcode->deserialized = 1;
Marko Mikulicic 0:c0ecb8bf28eb 13447
Marko Mikulicic 0:c0ecb8bf28eb 13448 /*
Marko Mikulicic 0:c0ecb8bf28eb 13449 * In serialized functions, all literals are inlined into `ops`, so we don't
Marko Mikulicic 0:c0ecb8bf28eb 13450 * deserialize them here in any way
Marko Mikulicic 0:c0ecb8bf28eb 13451 */
Marko Mikulicic 0:c0ecb8bf28eb 13452
Marko Mikulicic 0:c0ecb8bf28eb 13453 /* get number of args */
Marko Mikulicic 0:c0ecb8bf28eb 13454 bcode->args_cnt = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13455
Marko Mikulicic 0:c0ecb8bf28eb 13456 /* get number of names */
Marko Mikulicic 0:c0ecb8bf28eb 13457 bcode->names_cnt = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13458
Marko Mikulicic 0:c0ecb8bf28eb 13459 /* get whether the function name is present in `names` */
Marko Mikulicic 0:c0ecb8bf28eb 13460 bcode->func_name_present = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13461
Marko Mikulicic 0:c0ecb8bf28eb 13462 /* get opcode size */
Marko Mikulicic 0:c0ecb8bf28eb 13463 size = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13464
Marko Mikulicic 0:c0ecb8bf28eb 13465 bbuilder.ops.buf = (char *) data;
Marko Mikulicic 0:c0ecb8bf28eb 13466 bbuilder.ops.size = size;
Marko Mikulicic 0:c0ecb8bf28eb 13467 bbuilder.ops.len = size;
Marko Mikulicic 0:c0ecb8bf28eb 13468
Marko Mikulicic 0:c0ecb8bf28eb 13469 bcode->ops_in_rom = 1;
Marko Mikulicic 0:c0ecb8bf28eb 13470
Marko Mikulicic 0:c0ecb8bf28eb 13471 data += size;
Marko Mikulicic 0:c0ecb8bf28eb 13472
Marko Mikulicic 0:c0ecb8bf28eb 13473 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 13474 return data;
Marko Mikulicic 0:c0ecb8bf28eb 13475 }
Marko Mikulicic 0:c0ecb8bf28eb 13476
Marko Mikulicic 0:c0ecb8bf28eb 13477 V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13478 const char *data) {
Marko Mikulicic 0:c0ecb8bf28eb 13479 data = bcode_deserialize_func(v7, bcode, data);
Marko Mikulicic 0:c0ecb8bf28eb 13480 }
Marko Mikulicic 0:c0ecb8bf28eb 13481 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 13482 #line 1 "v7/src/eval.c"
Marko Mikulicic 0:c0ecb8bf28eb 13483 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13484 /*
Marko Mikulicic 0:c0ecb8bf28eb 13485 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 13486 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 13487 */
Marko Mikulicic 0:c0ecb8bf28eb 13488
Marko Mikulicic 0:c0ecb8bf28eb 13489 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13490 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13491 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13492 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13493 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13494 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13495 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13496 /* Amalgamated: #include "v7/src/compiler.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13497 /* Amalgamated: #include "v7/src/cyg_profile.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13498 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13499 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13500 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13501 /* Amalgamated: #include "v7/src/shdata.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13502 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13503 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13504 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13505
Marko Mikulicic 0:c0ecb8bf28eb 13506 /*
Marko Mikulicic 0:c0ecb8bf28eb 13507 * Bcode offsets in "try stack" are stored in JS numbers, i.e. in `double`s.
Marko Mikulicic 0:c0ecb8bf28eb 13508 * Apart from the offset itself, we also need some additional data:
Marko Mikulicic 0:c0ecb8bf28eb 13509 *
Marko Mikulicic 0:c0ecb8bf28eb 13510 * - type of the block that offset represents (`catch`, `finally`, `switch`,
Marko Mikulicic 0:c0ecb8bf28eb 13511 * or some loop)
Marko Mikulicic 0:c0ecb8bf28eb 13512 * - size of the stack when the block is created (needed when throwing, since
Marko Mikulicic 0:c0ecb8bf28eb 13513 * if exception is thrown from the middle of the expression, the stack may
Marko Mikulicic 0:c0ecb8bf28eb 13514 * have any arbitrary length)
Marko Mikulicic 0:c0ecb8bf28eb 13515 *
Marko Mikulicic 0:c0ecb8bf28eb 13516 * We bake all this data into integer part of the double (53 bits) :
Marko Mikulicic 0:c0ecb8bf28eb 13517 *
Marko Mikulicic 0:c0ecb8bf28eb 13518 * - 32 bits: bcode offset
Marko Mikulicic 0:c0ecb8bf28eb 13519 * - 3 bits: "tag": the type of the block
Marko Mikulicic 0:c0ecb8bf28eb 13520 * - 16 bits: stack size
Marko Mikulicic 0:c0ecb8bf28eb 13521 */
Marko Mikulicic 0:c0ecb8bf28eb 13522
Marko Mikulicic 0:c0ecb8bf28eb 13523 /*
Marko Mikulicic 0:c0ecb8bf28eb 13524 * Widths of data parts
Marko Mikulicic 0:c0ecb8bf28eb 13525 */
Marko Mikulicic 0:c0ecb8bf28eb 13526 #define LBLOCK_OFFSET_WIDTH 32
Marko Mikulicic 0:c0ecb8bf28eb 13527 #define LBLOCK_TAG_WIDTH 3
Marko Mikulicic 0:c0ecb8bf28eb 13528 #define LBLOCK_STACK_SIZE_WIDTH 16
Marko Mikulicic 0:c0ecb8bf28eb 13529
Marko Mikulicic 0:c0ecb8bf28eb 13530 /*
Marko Mikulicic 0:c0ecb8bf28eb 13531 * Shifts of data parts
Marko Mikulicic 0:c0ecb8bf28eb 13532 */
Marko Mikulicic 0:c0ecb8bf28eb 13533 #define LBLOCK_OFFSET_SHIFT (0)
Marko Mikulicic 0:c0ecb8bf28eb 13534 #define LBLOCK_TAG_SHIFT (LBLOCK_OFFSET_SHIFT + LBLOCK_OFFSET_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 13535 #define LBLOCK_STACK_SIZE_SHIFT (LBLOCK_TAG_SHIFT + LBLOCK_TAG_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 13536 #define LBLOCK_TOTAL_WIDTH (LBLOCK_STACK_SIZE_SHIFT + LBLOCK_STACK_SIZE_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 13537
Marko Mikulicic 0:c0ecb8bf28eb 13538 /*
Marko Mikulicic 0:c0ecb8bf28eb 13539 * Masks of data parts
Marko Mikulicic 0:c0ecb8bf28eb 13540 */
Marko Mikulicic 0:c0ecb8bf28eb 13541 #define LBLOCK_OFFSET_MASK \
Marko Mikulicic 0:c0ecb8bf28eb 13542 ((int64_t)(((int64_t) 1 << LBLOCK_OFFSET_WIDTH) - 1) << LBLOCK_OFFSET_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13543 #define LBLOCK_TAG_MASK \
Marko Mikulicic 0:c0ecb8bf28eb 13544 ((int64_t)(((int64_t) 1 << LBLOCK_TAG_WIDTH) - 1) << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13545 #define LBLOCK_STACK_SIZE_MASK \
Marko Mikulicic 0:c0ecb8bf28eb 13546 ((int64_t)(((int64_t) 1 << LBLOCK_STACK_SIZE_WIDTH) - 1) \
Marko Mikulicic 0:c0ecb8bf28eb 13547 << LBLOCK_STACK_SIZE_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13548
Marko Mikulicic 0:c0ecb8bf28eb 13549 /*
Marko Mikulicic 0:c0ecb8bf28eb 13550 * Self-check: make sure all the data can fit into double's mantissa
Marko Mikulicic 0:c0ecb8bf28eb 13551 */
Marko Mikulicic 0:c0ecb8bf28eb 13552 #if (LBLOCK_TOTAL_WIDTH > 53)
Marko Mikulicic 0:c0ecb8bf28eb 13553 #error lblock width is too large, it can't fit into double's mantissa
Marko Mikulicic 0:c0ecb8bf28eb 13554 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13555
Marko Mikulicic 0:c0ecb8bf28eb 13556 /*
Marko Mikulicic 0:c0ecb8bf28eb 13557 * Tags that are used for bcode offsets in "try stack"
Marko Mikulicic 0:c0ecb8bf28eb 13558 */
Marko Mikulicic 0:c0ecb8bf28eb 13559 #define LBLOCK_TAG_CATCH ((int64_t) 0x01 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13560 #define LBLOCK_TAG_FINALLY ((int64_t) 0x02 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13561 #define LBLOCK_TAG_LOOP ((int64_t) 0x03 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13562 #define LBLOCK_TAG_SWITCH ((int64_t) 0x04 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13563
Marko Mikulicic 0:c0ecb8bf28eb 13564 /*
Marko Mikulicic 0:c0ecb8bf28eb 13565 * Yields 32-bit bcode offset value
Marko Mikulicic 0:c0ecb8bf28eb 13566 */
Marko Mikulicic 0:c0ecb8bf28eb 13567 #define LBLOCK_OFFSET(v) \
Marko Mikulicic 0:c0ecb8bf28eb 13568 ((bcode_off_t)(((v) &LBLOCK_OFFSET_MASK) >> LBLOCK_OFFSET_SHIFT))
Marko Mikulicic 0:c0ecb8bf28eb 13569
Marko Mikulicic 0:c0ecb8bf28eb 13570 /*
Marko Mikulicic 0:c0ecb8bf28eb 13571 * Yields tag value (unshifted, to be compared with macros like
Marko Mikulicic 0:c0ecb8bf28eb 13572 * `LBLOCK_TAG_CATCH`, etc)
Marko Mikulicic 0:c0ecb8bf28eb 13573 */
Marko Mikulicic 0:c0ecb8bf28eb 13574 #define LBLOCK_TAG(v) ((v) &LBLOCK_TAG_MASK)
Marko Mikulicic 0:c0ecb8bf28eb 13575
Marko Mikulicic 0:c0ecb8bf28eb 13576 /*
Marko Mikulicic 0:c0ecb8bf28eb 13577 * Yields stack size
Marko Mikulicic 0:c0ecb8bf28eb 13578 */
Marko Mikulicic 0:c0ecb8bf28eb 13579 #define LBLOCK_STACK_SIZE(v) \
Marko Mikulicic 0:c0ecb8bf28eb 13580 (((v) &LBLOCK_STACK_SIZE_MASK) >> LBLOCK_STACK_SIZE_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13581
Marko Mikulicic 0:c0ecb8bf28eb 13582 /*
Marko Mikulicic 0:c0ecb8bf28eb 13583 * Yields `int64_t` value to be stored as a JavaScript number
Marko Mikulicic 0:c0ecb8bf28eb 13584 */
Marko Mikulicic 0:c0ecb8bf28eb 13585 #define LBLOCK_ITEM_CREATE(offset, tag, stack_size) \
Marko Mikulicic 0:c0ecb8bf28eb 13586 ((int64_t)(offset) | (tag) | \
Marko Mikulicic 0:c0ecb8bf28eb 13587 (((int64_t)(stack_size)) << LBLOCK_STACK_SIZE_SHIFT))
Marko Mikulicic 0:c0ecb8bf28eb 13588
Marko Mikulicic 0:c0ecb8bf28eb 13589 /*
Marko Mikulicic 0:c0ecb8bf28eb 13590 * make sure `bcode_off_t` is just 32-bit, so that it can fit in double
Marko Mikulicic 0:c0ecb8bf28eb 13591 * with 3-bit tag
Marko Mikulicic 0:c0ecb8bf28eb 13592 */
Marko Mikulicic 0:c0ecb8bf28eb 13593 V7_STATIC_ASSERT((sizeof(bcode_off_t) * 8) == LBLOCK_OFFSET_WIDTH,
Marko Mikulicic 0:c0ecb8bf28eb 13594 wrong_size_of_bcode_off_t);
Marko Mikulicic 0:c0ecb8bf28eb 13595
Marko Mikulicic 0:c0ecb8bf28eb 13596 #define PUSH(v) stack_push(&v7->stack, v)
Marko Mikulicic 0:c0ecb8bf28eb 13597 #define POP() stack_pop(&v7->stack)
Marko Mikulicic 0:c0ecb8bf28eb 13598 #define TOS() stack_tos(&v7->stack)
Marko Mikulicic 0:c0ecb8bf28eb 13599 #define SP() stack_sp(&v7->stack)
Marko Mikulicic 0:c0ecb8bf28eb 13600
Marko Mikulicic 0:c0ecb8bf28eb 13601 /*
Marko Mikulicic 0:c0ecb8bf28eb 13602 * Local-to-function block types that we might want to consider when unwinding
Marko Mikulicic 0:c0ecb8bf28eb 13603 * stack for whatever reason. see `unwind_local_blocks_stack()`.
Marko Mikulicic 0:c0ecb8bf28eb 13604 */
Marko Mikulicic 0:c0ecb8bf28eb 13605 enum local_block {
Marko Mikulicic 0:c0ecb8bf28eb 13606 LOCAL_BLOCK_NONE = (0),
Marko Mikulicic 0:c0ecb8bf28eb 13607 LOCAL_BLOCK_CATCH = (1 << 0),
Marko Mikulicic 0:c0ecb8bf28eb 13608 LOCAL_BLOCK_FINALLY = (1 << 1),
Marko Mikulicic 0:c0ecb8bf28eb 13609 LOCAL_BLOCK_LOOP = (1 << 2),
Marko Mikulicic 0:c0ecb8bf28eb 13610 LOCAL_BLOCK_SWITCH = (1 << 3),
Marko Mikulicic 0:c0ecb8bf28eb 13611 };
Marko Mikulicic 0:c0ecb8bf28eb 13612
Marko Mikulicic 0:c0ecb8bf28eb 13613 /*
Marko Mikulicic 0:c0ecb8bf28eb 13614 * Like `V7_TRY()`, but to be used inside `eval_bcode()` only: you should
Marko Mikulicic 0:c0ecb8bf28eb 13615 * wrap all calls to cfunctions into `BTRY()` instead of `V7_TRY()`.
Marko Mikulicic 0:c0ecb8bf28eb 13616 *
Marko Mikulicic 0:c0ecb8bf28eb 13617 * If the provided function returns something other than `V7_OK`, this macro
Marko Mikulicic 0:c0ecb8bf28eb 13618 * calls `bcode_perform_throw`, which performs bcode stack unwinding.
Marko Mikulicic 0:c0ecb8bf28eb 13619 */
Marko Mikulicic 0:c0ecb8bf28eb 13620 #define BTRY(call) \
Marko Mikulicic 0:c0ecb8bf28eb 13621 do { \
Marko Mikulicic 0:c0ecb8bf28eb 13622 enum v7_err _e = call; \
Marko Mikulicic 0:c0ecb8bf28eb 13623 (void) _you_should_use_BTRY_in_eval_bcode_only; \
Marko Mikulicic 0:c0ecb8bf28eb 13624 if (_e != V7_OK) { \
Marko Mikulicic 0:c0ecb8bf28eb 13625 V7_TRY(bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/)); \
Marko Mikulicic 0:c0ecb8bf28eb 13626 goto op_done; \
Marko Mikulicic 0:c0ecb8bf28eb 13627 } \
Marko Mikulicic 0:c0ecb8bf28eb 13628 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 13629
Marko Mikulicic 0:c0ecb8bf28eb 13630 V7_PRIVATE void stack_push(struct mbuf *s, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 13631 mbuf_append(s, &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 13632 }
Marko Mikulicic 0:c0ecb8bf28eb 13633
Marko Mikulicic 0:c0ecb8bf28eb 13634 V7_PRIVATE val_t stack_pop(struct mbuf *s) {
Marko Mikulicic 0:c0ecb8bf28eb 13635 assert(s->len >= sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13636 s->len -= sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 13637 return *(val_t *) (s->buf + s->len);
Marko Mikulicic 0:c0ecb8bf28eb 13638 }
Marko Mikulicic 0:c0ecb8bf28eb 13639
Marko Mikulicic 0:c0ecb8bf28eb 13640 V7_PRIVATE val_t stack_tos(struct mbuf *s) {
Marko Mikulicic 0:c0ecb8bf28eb 13641 assert(s->len >= sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13642 return *(val_t *) (s->buf + s->len - sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13643 }
Marko Mikulicic 0:c0ecb8bf28eb 13644
Marko Mikulicic 0:c0ecb8bf28eb 13645 #ifdef V7_BCODE_TRACE_STACK
Marko Mikulicic 0:c0ecb8bf28eb 13646 V7_PRIVATE val_t stack_at(struct mbuf *s, size_t idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13647 assert(s->len >= sizeof(val_t) * idx);
Marko Mikulicic 0:c0ecb8bf28eb 13648 return *(val_t *) (s->buf + s->len - sizeof(val_t) - idx * sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13649 }
Marko Mikulicic 0:c0ecb8bf28eb 13650 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13651
Marko Mikulicic 0:c0ecb8bf28eb 13652 V7_PRIVATE int stack_sp(struct mbuf *s) {
Marko Mikulicic 0:c0ecb8bf28eb 13653 return s->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 13654 }
Marko Mikulicic 0:c0ecb8bf28eb 13655
Marko Mikulicic 0:c0ecb8bf28eb 13656 /*
Marko Mikulicic 0:c0ecb8bf28eb 13657 * Delete a property with name `name`, `len` from an object `obj`. If the
Marko Mikulicic 0:c0ecb8bf28eb 13658 * object does not contain own property with the given `name`, moves to `obj`'s
Marko Mikulicic 0:c0ecb8bf28eb 13659 * prototype, and so on.
Marko Mikulicic 0:c0ecb8bf28eb 13660 *
Marko Mikulicic 0:c0ecb8bf28eb 13661 * If the property is eventually found, it is deleted, and `0` is returned.
Marko Mikulicic 0:c0ecb8bf28eb 13662 * Otherwise, `-1` is returned.
Marko Mikulicic 0:c0ecb8bf28eb 13663 *
Marko Mikulicic 0:c0ecb8bf28eb 13664 * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 13665 *
Marko Mikulicic 0:c0ecb8bf28eb 13666 * See `v7_del()` as well.
Marko Mikulicic 0:c0ecb8bf28eb 13667 */
Marko Mikulicic 0:c0ecb8bf28eb 13668 static int del_property_deep(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 13669 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 13670 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 13671 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 13672 }
Marko Mikulicic 0:c0ecb8bf28eb 13673 for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 13674 int del_res;
Marko Mikulicic 0:c0ecb8bf28eb 13675 if ((del_res = v7_del(v7, obj, name, len)) != -1) {
Marko Mikulicic 0:c0ecb8bf28eb 13676 return del_res;
Marko Mikulicic 0:c0ecb8bf28eb 13677 }
Marko Mikulicic 0:c0ecb8bf28eb 13678 }
Marko Mikulicic 0:c0ecb8bf28eb 13679 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 13680 }
Marko Mikulicic 0:c0ecb8bf28eb 13681
Marko Mikulicic 0:c0ecb8bf28eb 13682 /* Visual studio 2012+ has signbit() */
Marko Mikulicic 0:c0ecb8bf28eb 13683 #if defined(_MSC_VER) && _MSC_VER < 1700
Marko Mikulicic 0:c0ecb8bf28eb 13684 static int signbit(double x) {
Marko Mikulicic 0:c0ecb8bf28eb 13685 double s = _copysign(1, x);
Marko Mikulicic 0:c0ecb8bf28eb 13686 return s < 0;
Marko Mikulicic 0:c0ecb8bf28eb 13687 }
Marko Mikulicic 0:c0ecb8bf28eb 13688 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13689
Marko Mikulicic 0:c0ecb8bf28eb 13690 static double b_int_bin_op(enum opcode op, double a, double b) {
Marko Mikulicic 0:c0ecb8bf28eb 13691 int32_t ia = isnan(a) || isinf(a) ? 0 : (int32_t)(int64_t) a;
Marko Mikulicic 0:c0ecb8bf28eb 13692 int32_t ib = isnan(b) || isinf(b) ? 0 : (int32_t)(int64_t) b;
Marko Mikulicic 0:c0ecb8bf28eb 13693
Marko Mikulicic 0:c0ecb8bf28eb 13694 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13695 case OP_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13696 return (int32_t)((uint32_t) ia << ((uint32_t) ib & 31));
Marko Mikulicic 0:c0ecb8bf28eb 13697 case OP_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13698 return ia >> ((uint32_t) ib & 31);
Marko Mikulicic 0:c0ecb8bf28eb 13699 case OP_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13700 return (uint32_t) ia >> ((uint32_t) ib & 31);
Marko Mikulicic 0:c0ecb8bf28eb 13701 case OP_OR:
Marko Mikulicic 0:c0ecb8bf28eb 13702 return ia | ib;
Marko Mikulicic 0:c0ecb8bf28eb 13703 case OP_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 13704 return ia ^ ib;
Marko Mikulicic 0:c0ecb8bf28eb 13705 case OP_AND:
Marko Mikulicic 0:c0ecb8bf28eb 13706 return ia & ib;
Marko Mikulicic 0:c0ecb8bf28eb 13707 default:
Marko Mikulicic 0:c0ecb8bf28eb 13708 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 13709 }
Marko Mikulicic 0:c0ecb8bf28eb 13710 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 13711 }
Marko Mikulicic 0:c0ecb8bf28eb 13712
Marko Mikulicic 0:c0ecb8bf28eb 13713 static double b_num_bin_op(enum opcode op, double a, double b) {
Marko Mikulicic 0:c0ecb8bf28eb 13714 /*
Marko Mikulicic 0:c0ecb8bf28eb 13715 * For certain operations, the result is always NaN if either of arguments
Marko Mikulicic 0:c0ecb8bf28eb 13716 * is NaN
Marko Mikulicic 0:c0ecb8bf28eb 13717 */
Marko Mikulicic 0:c0ecb8bf28eb 13718 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13719 case OP_ADD:
Marko Mikulicic 0:c0ecb8bf28eb 13720 case OP_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 13721 case OP_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 13722 case OP_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 13723 case OP_REM:
Marko Mikulicic 0:c0ecb8bf28eb 13724 if (isnan(a) || isnan(b)) {
Marko Mikulicic 0:c0ecb8bf28eb 13725 return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 13726 }
Marko Mikulicic 0:c0ecb8bf28eb 13727 break;
Marko Mikulicic 0:c0ecb8bf28eb 13728 default:
Marko Mikulicic 0:c0ecb8bf28eb 13729 break;
Marko Mikulicic 0:c0ecb8bf28eb 13730 }
Marko Mikulicic 0:c0ecb8bf28eb 13731
Marko Mikulicic 0:c0ecb8bf28eb 13732 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13733 case OP_ADD: /* simple fixed width nodes with no payload */
Marko Mikulicic 0:c0ecb8bf28eb 13734 return a + b;
Marko Mikulicic 0:c0ecb8bf28eb 13735 case OP_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 13736 return a - b;
Marko Mikulicic 0:c0ecb8bf28eb 13737 case OP_REM:
Marko Mikulicic 0:c0ecb8bf28eb 13738 if (b == 0 || isnan(b) || isnan(a) || isinf(b) || isinf(a)) {
Marko Mikulicic 0:c0ecb8bf28eb 13739 return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 13740 }
Marko Mikulicic 0:c0ecb8bf28eb 13741 return (int) a % (int) b;
Marko Mikulicic 0:c0ecb8bf28eb 13742 case OP_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 13743 return a * b;
Marko Mikulicic 0:c0ecb8bf28eb 13744 case OP_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 13745 if (b == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 13746 if (a == 0) return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 13747 return (!signbit(a) == !signbit(b)) ? INFINITY : -INFINITY;
Marko Mikulicic 0:c0ecb8bf28eb 13748 }
Marko Mikulicic 0:c0ecb8bf28eb 13749 return a / b;
Marko Mikulicic 0:c0ecb8bf28eb 13750 case OP_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13751 case OP_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13752 case OP_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13753 case OP_OR:
Marko Mikulicic 0:c0ecb8bf28eb 13754 case OP_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 13755 case OP_AND:
Marko Mikulicic 0:c0ecb8bf28eb 13756 return b_int_bin_op(op, a, b);
Marko Mikulicic 0:c0ecb8bf28eb 13757 default:
Marko Mikulicic 0:c0ecb8bf28eb 13758 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 13759 }
Marko Mikulicic 0:c0ecb8bf28eb 13760 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 13761 }
Marko Mikulicic 0:c0ecb8bf28eb 13762
Marko Mikulicic 0:c0ecb8bf28eb 13763 static int b_bool_bin_op(enum opcode op, double a, double b) {
Marko Mikulicic 0:c0ecb8bf28eb 13764 #ifdef V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 13765 if (isnan(a) || isnan(b)) return op == OP_NE || op == OP_NE_NE;
Marko Mikulicic 0:c0ecb8bf28eb 13766 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13767
Marko Mikulicic 0:c0ecb8bf28eb 13768 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13769 case OP_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 13770 case OP_EQ_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 13771 return a == b;
Marko Mikulicic 0:c0ecb8bf28eb 13772 case OP_NE:
Marko Mikulicic 0:c0ecb8bf28eb 13773 case OP_NE_NE:
Marko Mikulicic 0:c0ecb8bf28eb 13774 return a != b;
Marko Mikulicic 0:c0ecb8bf28eb 13775 case OP_LT:
Marko Mikulicic 0:c0ecb8bf28eb 13776 return a < b;
Marko Mikulicic 0:c0ecb8bf28eb 13777 case OP_LE:
Marko Mikulicic 0:c0ecb8bf28eb 13778 return a <= b;
Marko Mikulicic 0:c0ecb8bf28eb 13779 case OP_GT:
Marko Mikulicic 0:c0ecb8bf28eb 13780 return a > b;
Marko Mikulicic 0:c0ecb8bf28eb 13781 case OP_GE:
Marko Mikulicic 0:c0ecb8bf28eb 13782 return a >= b;
Marko Mikulicic 0:c0ecb8bf28eb 13783 default:
Marko Mikulicic 0:c0ecb8bf28eb 13784 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 13785 }
Marko Mikulicic 0:c0ecb8bf28eb 13786 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 13787 }
Marko Mikulicic 0:c0ecb8bf28eb 13788
Marko Mikulicic 0:c0ecb8bf28eb 13789 static bcode_off_t bcode_get_target(char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 13790 bcode_off_t target;
Marko Mikulicic 0:c0ecb8bf28eb 13791 (*ops)++;
Marko Mikulicic 0:c0ecb8bf28eb 13792 memcpy(&target, *ops, sizeof(target));
Marko Mikulicic 0:c0ecb8bf28eb 13793 *ops += sizeof(target) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 13794 return target;
Marko Mikulicic 0:c0ecb8bf28eb 13795 }
Marko Mikulicic 0:c0ecb8bf28eb 13796
Marko Mikulicic 0:c0ecb8bf28eb 13797 struct bcode_registers {
Marko Mikulicic 0:c0ecb8bf28eb 13798 /*
Marko Mikulicic 0:c0ecb8bf28eb 13799 * TODO(dfrank): make it contain `struct v7_call_frame_bcode *`
Marko Mikulicic 0:c0ecb8bf28eb 13800 * and use `bcode_ops` in-place, or probably drop the `bcode_registers`
Marko Mikulicic 0:c0ecb8bf28eb 13801 * whatsoever
Marko Mikulicic 0:c0ecb8bf28eb 13802 */
Marko Mikulicic 0:c0ecb8bf28eb 13803 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13804 char *ops;
Marko Mikulicic 0:c0ecb8bf28eb 13805 char *end;
Marko Mikulicic 0:c0ecb8bf28eb 13806 unsigned int need_inc_ops : 1;
Marko Mikulicic 0:c0ecb8bf28eb 13807 };
Marko Mikulicic 0:c0ecb8bf28eb 13808
Marko Mikulicic 0:c0ecb8bf28eb 13809 /*
Marko Mikulicic 0:c0ecb8bf28eb 13810 * If returning from function implicitly, then set return value to `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 13811 *
Marko Mikulicic 0:c0ecb8bf28eb 13812 * And if function was called as a constructor, then make sure returned
Marko Mikulicic 0:c0ecb8bf28eb 13813 * value is an object.
Marko Mikulicic 0:c0ecb8bf28eb 13814 */
Marko Mikulicic 0:c0ecb8bf28eb 13815 static void bcode_adjust_retval(struct v7 *v7, uint8_t is_explicit_return) {
Marko Mikulicic 0:c0ecb8bf28eb 13816 if (!is_explicit_return) {
Marko Mikulicic 0:c0ecb8bf28eb 13817 /* returning implicitly: set return value to `undefined` */
Marko Mikulicic 0:c0ecb8bf28eb 13818 POP();
Marko Mikulicic 0:c0ecb8bf28eb 13819 PUSH(V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 13820 }
Marko Mikulicic 0:c0ecb8bf28eb 13821
Marko Mikulicic 0:c0ecb8bf28eb 13822 if (v7->call_stack->is_constructor && !v7_is_object(TOS())) {
Marko Mikulicic 0:c0ecb8bf28eb 13823 /* constructor is going to return non-object: replace it with `this` */
Marko Mikulicic 0:c0ecb8bf28eb 13824 POP();
Marko Mikulicic 0:c0ecb8bf28eb 13825 PUSH(v7_get_this(v7));
Marko Mikulicic 0:c0ecb8bf28eb 13826 }
Marko Mikulicic 0:c0ecb8bf28eb 13827 }
Marko Mikulicic 0:c0ecb8bf28eb 13828
Marko Mikulicic 0:c0ecb8bf28eb 13829 static void bcode_restore_registers(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13830 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 13831 r->bcode = bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13832 r->ops = bcode->ops.p;
Marko Mikulicic 0:c0ecb8bf28eb 13833 r->end = r->ops + bcode->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 13834
Marko Mikulicic 0:c0ecb8bf28eb 13835 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 13836 }
Marko Mikulicic 0:c0ecb8bf28eb 13837
Marko Mikulicic 0:c0ecb8bf28eb 13838 V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13839 uint8_t type_mask) {
Marko Mikulicic 0:c0ecb8bf28eb 13840 struct v7_call_frame_base *ret = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 13841
Marko Mikulicic 0:c0ecb8bf28eb 13842 while (ret != NULL && !(ret->type_mask & type_mask)) {
Marko Mikulicic 0:c0ecb8bf28eb 13843 ret = ret->prev;
Marko Mikulicic 0:c0ecb8bf28eb 13844 }
Marko Mikulicic 0:c0ecb8bf28eb 13845
Marko Mikulicic 0:c0ecb8bf28eb 13846 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 13847 }
Marko Mikulicic 0:c0ecb8bf28eb 13848
Marko Mikulicic 0:c0ecb8bf28eb 13849 static struct v7_call_frame_private *find_call_frame_private(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 13850 return (struct v7_call_frame_private *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 13851 v7, V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 13852 }
Marko Mikulicic 0:c0ecb8bf28eb 13853
Marko Mikulicic 0:c0ecb8bf28eb 13854 static struct v7_call_frame_bcode *find_call_frame_bcode(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 13855 return (struct v7_call_frame_bcode *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 13856 v7, V7_CALL_FRAME_MASK_BCODE);
Marko Mikulicic 0:c0ecb8bf28eb 13857 }
Marko Mikulicic 0:c0ecb8bf28eb 13858
Marko Mikulicic 0:c0ecb8bf28eb 13859 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 13860 static struct v7_call_frame_cfunc *find_call_frame_cfunc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 13861 return (struct v7_call_frame_cfunc *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 13862 v7, V7_CALL_FRAME_MASK_CFUNC);
Marko Mikulicic 0:c0ecb8bf28eb 13863 }
Marko Mikulicic 0:c0ecb8bf28eb 13864 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13865
Marko Mikulicic 0:c0ecb8bf28eb 13866 static struct v7_call_frame_base *create_call_frame(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13867 size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 13868 struct v7_call_frame_base *call_frame_base = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 13869
Marko Mikulicic 0:c0ecb8bf28eb 13870 call_frame_base = (struct v7_call_frame_base *) calloc(1, size);
Marko Mikulicic 0:c0ecb8bf28eb 13871
Marko Mikulicic 0:c0ecb8bf28eb 13872 /* save previous call frame */
Marko Mikulicic 0:c0ecb8bf28eb 13873 call_frame_base->prev = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 13874
Marko Mikulicic 0:c0ecb8bf28eb 13875 /* by default, inherit line_no from the previous frame */
Marko Mikulicic 0:c0ecb8bf28eb 13876 if (v7->call_stack != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13877 call_frame_base->line_no = v7->call_stack->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 13878 }
Marko Mikulicic 0:c0ecb8bf28eb 13879
Marko Mikulicic 0:c0ecb8bf28eb 13880 return call_frame_base;
Marko Mikulicic 0:c0ecb8bf28eb 13881 }
Marko Mikulicic 0:c0ecb8bf28eb 13882
Marko Mikulicic 0:c0ecb8bf28eb 13883 static void init_call_frame_private(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13884 struct v7_call_frame_private *call_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13885 val_t scope) {
Marko Mikulicic 0:c0ecb8bf28eb 13886 /* make a snapshot of the current state */
Marko Mikulicic 0:c0ecb8bf28eb 13887 {
Marko Mikulicic 0:c0ecb8bf28eb 13888 struct v7_call_frame_private *cf = find_call_frame_private(v7);
Marko Mikulicic 0:c0ecb8bf28eb 13889 if (cf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13890 cf->stack_size = v7->stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 13891 }
Marko Mikulicic 0:c0ecb8bf28eb 13892 }
Marko Mikulicic 0:c0ecb8bf28eb 13893
Marko Mikulicic 0:c0ecb8bf28eb 13894 /* set a type flag */
Marko Mikulicic 0:c0ecb8bf28eb 13895 call_frame->base.type_mask |= V7_CALL_FRAME_MASK_PRIVATE;
Marko Mikulicic 0:c0ecb8bf28eb 13896
Marko Mikulicic 0:c0ecb8bf28eb 13897 /* fill the new frame with data */
Marko Mikulicic 0:c0ecb8bf28eb 13898 call_frame->vals.scope = scope;
Marko Mikulicic 0:c0ecb8bf28eb 13899 /* `try_stack` will be lazily created in `eval_try_push()`*/
Marko Mikulicic 0:c0ecb8bf28eb 13900 call_frame->vals.try_stack = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 13901 }
Marko Mikulicic 0:c0ecb8bf28eb 13902
Marko Mikulicic 0:c0ecb8bf28eb 13903 static void init_call_frame_bcode(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13904 struct v7_call_frame_bcode *call_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13905 char *prev_bcode_ops, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13906 val_t this_obj, val_t scope,
Marko Mikulicic 0:c0ecb8bf28eb 13907 uint8_t is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 13908 init_call_frame_private(v7, &call_frame->base, scope);
Marko Mikulicic 0:c0ecb8bf28eb 13909
Marko Mikulicic 0:c0ecb8bf28eb 13910 /* make a snapshot of the current state */
Marko Mikulicic 0:c0ecb8bf28eb 13911 {
Marko Mikulicic 0:c0ecb8bf28eb 13912 struct v7_call_frame_bcode *cf = find_call_frame_bcode(v7);
Marko Mikulicic 0:c0ecb8bf28eb 13913 if (cf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13914 cf->bcode_ops = prev_bcode_ops;
Marko Mikulicic 0:c0ecb8bf28eb 13915
Marko Mikulicic 0:c0ecb8bf28eb 13916 /* remember thrown value */
Marko Mikulicic 0:c0ecb8bf28eb 13917 cf->vals.thrown_error = v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 13918 cf->base.base.is_thrown = v7->is_thrown;
Marko Mikulicic 0:c0ecb8bf28eb 13919 }
Marko Mikulicic 0:c0ecb8bf28eb 13920 }
Marko Mikulicic 0:c0ecb8bf28eb 13921
Marko Mikulicic 0:c0ecb8bf28eb 13922 /* set a type flag */
Marko Mikulicic 0:c0ecb8bf28eb 13923 call_frame->base.base.type_mask |= V7_CALL_FRAME_MASK_BCODE;
Marko Mikulicic 0:c0ecb8bf28eb 13924
Marko Mikulicic 0:c0ecb8bf28eb 13925 /* fill the new frame with data */
Marko Mikulicic 0:c0ecb8bf28eb 13926 call_frame->bcode = bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13927 call_frame->vals.this_obj = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 13928 call_frame->base.base.is_constructor = is_constructor;
Marko Mikulicic 0:c0ecb8bf28eb 13929 }
Marko Mikulicic 0:c0ecb8bf28eb 13930
Marko Mikulicic 0:c0ecb8bf28eb 13931 /*
Marko Mikulicic 0:c0ecb8bf28eb 13932 * Create new bcode call frame object and fill it with data
Marko Mikulicic 0:c0ecb8bf28eb 13933 */
Marko Mikulicic 0:c0ecb8bf28eb 13934 static void append_call_frame_bcode(struct v7 *v7, char *prev_bcode_ops,
Marko Mikulicic 0:c0ecb8bf28eb 13935 struct bcode *bcode, val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 13936 val_t scope, uint8_t is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 13937 struct v7_call_frame_bcode *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 13938 (struct v7_call_frame_bcode *) create_call_frame(v7, sizeof(*call_frame));
Marko Mikulicic 0:c0ecb8bf28eb 13939
Marko Mikulicic 0:c0ecb8bf28eb 13940 init_call_frame_bcode(v7, call_frame, prev_bcode_ops, bcode, this_obj, scope,
Marko Mikulicic 0:c0ecb8bf28eb 13941 is_constructor);
Marko Mikulicic 0:c0ecb8bf28eb 13942
Marko Mikulicic 0:c0ecb8bf28eb 13943 v7->call_stack = &call_frame->base.base;
Marko Mikulicic 0:c0ecb8bf28eb 13944 }
Marko Mikulicic 0:c0ecb8bf28eb 13945
Marko Mikulicic 0:c0ecb8bf28eb 13946 static void append_call_frame_private(struct v7 *v7, val_t scope) {
Marko Mikulicic 0:c0ecb8bf28eb 13947 struct v7_call_frame_private *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 13948 (struct v7_call_frame_private *) create_call_frame(v7,
Marko Mikulicic 0:c0ecb8bf28eb 13949 sizeof(*call_frame));
Marko Mikulicic 0:c0ecb8bf28eb 13950 init_call_frame_private(v7, call_frame, scope);
Marko Mikulicic 0:c0ecb8bf28eb 13951
Marko Mikulicic 0:c0ecb8bf28eb 13952 v7->call_stack = &call_frame->base;
Marko Mikulicic 0:c0ecb8bf28eb 13953 }
Marko Mikulicic 0:c0ecb8bf28eb 13954
Marko Mikulicic 0:c0ecb8bf28eb 13955 static void append_call_frame_cfunc(struct v7 *v7, val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 13956 v7_cfunction_t *cfunc) {
Marko Mikulicic 0:c0ecb8bf28eb 13957 struct v7_call_frame_cfunc *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 13958 (struct v7_call_frame_cfunc *) create_call_frame(v7, sizeof(*call_frame));
Marko Mikulicic 0:c0ecb8bf28eb 13959
Marko Mikulicic 0:c0ecb8bf28eb 13960 /* set a type flag */
Marko Mikulicic 0:c0ecb8bf28eb 13961 call_frame->base.type_mask |= V7_CALL_FRAME_MASK_CFUNC;
Marko Mikulicic 0:c0ecb8bf28eb 13962
Marko Mikulicic 0:c0ecb8bf28eb 13963 /* fill the new frame with data */
Marko Mikulicic 0:c0ecb8bf28eb 13964 call_frame->cfunc = cfunc;
Marko Mikulicic 0:c0ecb8bf28eb 13965 call_frame->vals.this_obj = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 13966
Marko Mikulicic 0:c0ecb8bf28eb 13967 v7->call_stack = &call_frame->base;
Marko Mikulicic 0:c0ecb8bf28eb 13968 }
Marko Mikulicic 0:c0ecb8bf28eb 13969
Marko Mikulicic 0:c0ecb8bf28eb 13970 /*
Marko Mikulicic 0:c0ecb8bf28eb 13971 * The caller's bcode object is needed because we have to restore literals
Marko Mikulicic 0:c0ecb8bf28eb 13972 * and `end` registers.
Marko Mikulicic 0:c0ecb8bf28eb 13973 *
Marko Mikulicic 0:c0ecb8bf28eb 13974 * TODO(mkm): put this state on a return stack
Marko Mikulicic 0:c0ecb8bf28eb 13975 *
Marko Mikulicic 0:c0ecb8bf28eb 13976 * Caller of bcode_perform_call is responsible for owning `call_frame`
Marko Mikulicic 0:c0ecb8bf28eb 13977 */
Marko Mikulicic 0:c0ecb8bf28eb 13978 static enum v7_err bcode_perform_call(struct v7 *v7, v7_val_t scope_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13979 struct v7_js_function *func,
Marko Mikulicic 0:c0ecb8bf28eb 13980 struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 13981 val_t this_object, char *ops,
Marko Mikulicic 0:c0ecb8bf28eb 13982 uint8_t is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 13983 /* new scope_frame will inherit from the function's scope */
Marko Mikulicic 0:c0ecb8bf28eb 13984 obj_prototype_set(v7, get_object_struct(scope_frame), &func->scope->base);
Marko Mikulicic 0:c0ecb8bf28eb 13985
Marko Mikulicic 0:c0ecb8bf28eb 13986 /* create new `call_frame` which will replace `v7->call_stack` */
Marko Mikulicic 0:c0ecb8bf28eb 13987 append_call_frame_bcode(v7, r->ops + 1, func->bcode, this_object, scope_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13988 is_constructor);
Marko Mikulicic 0:c0ecb8bf28eb 13989
Marko Mikulicic 0:c0ecb8bf28eb 13990 bcode_restore_registers(v7, func->bcode, r);
Marko Mikulicic 0:c0ecb8bf28eb 13991
Marko Mikulicic 0:c0ecb8bf28eb 13992 /* adjust `ops` since names were already read from it */
Marko Mikulicic 0:c0ecb8bf28eb 13993 r->ops = ops;
Marko Mikulicic 0:c0ecb8bf28eb 13994
Marko Mikulicic 0:c0ecb8bf28eb 13995 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 13996 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13997
Marko Mikulicic 0:c0ecb8bf28eb 13998 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 13999 }
Marko Mikulicic 0:c0ecb8bf28eb 14000
Marko Mikulicic 0:c0ecb8bf28eb 14001 /*
Marko Mikulicic 0:c0ecb8bf28eb 14002 * Apply data from the "private" call frame, typically after some other frame
Marko Mikulicic 0:c0ecb8bf28eb 14003 * was just unwound.
Marko Mikulicic 0:c0ecb8bf28eb 14004 *
Marko Mikulicic 0:c0ecb8bf28eb 14005 * The `call_frame` may actually be `NULL`, if the top frame was unwound.
Marko Mikulicic 0:c0ecb8bf28eb 14006 */
Marko Mikulicic 0:c0ecb8bf28eb 14007 static void apply_frame_private(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14008 struct v7_call_frame_private *call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 14009 /*
Marko Mikulicic 0:c0ecb8bf28eb 14010 * Adjust data stack length (restore saved).
Marko Mikulicic 0:c0ecb8bf28eb 14011 *
Marko Mikulicic 0:c0ecb8bf28eb 14012 * If `call_frame` is NULL, it means that the last call frame was just
Marko Mikulicic 0:c0ecb8bf28eb 14013 * unwound, and hence the data stack size should be 0.
Marko Mikulicic 0:c0ecb8bf28eb 14014 */
Marko Mikulicic 0:c0ecb8bf28eb 14015 size_t stack_size = (call_frame != NULL ? call_frame->stack_size : 0);
Marko Mikulicic 0:c0ecb8bf28eb 14016 assert(stack_size <= v7->stack.len);
Marko Mikulicic 0:c0ecb8bf28eb 14017 v7->stack.len = stack_size;
Marko Mikulicic 0:c0ecb8bf28eb 14018 }
Marko Mikulicic 0:c0ecb8bf28eb 14019
Marko Mikulicic 0:c0ecb8bf28eb 14020 /*
Marko Mikulicic 0:c0ecb8bf28eb 14021 * Apply data from the "bcode" call frame, typically after some other frame
Marko Mikulicic 0:c0ecb8bf28eb 14022 * was just unwound.
Marko Mikulicic 0:c0ecb8bf28eb 14023 *
Marko Mikulicic 0:c0ecb8bf28eb 14024 * The `call_frame` may actually be `NULL`, if the top frame was unwound; but
Marko Mikulicic 0:c0ecb8bf28eb 14025 * in this case, `r` must be `NULL` too, by design. See inline comment below.
Marko Mikulicic 0:c0ecb8bf28eb 14026 */
Marko Mikulicic 0:c0ecb8bf28eb 14027 static void apply_frame_bcode(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14028 struct v7_call_frame_bcode *call_frame,
Marko Mikulicic 0:c0ecb8bf28eb 14029 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 14030 if (r != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 14031 /*
Marko Mikulicic 0:c0ecb8bf28eb 14032 * Note: if `r` is non-NULL, then `call_frame` should be non-NULL as well,
Marko Mikulicic 0:c0ecb8bf28eb 14033 * by design. If this invariant is violated, it means that
Marko Mikulicic 0:c0ecb8bf28eb 14034 * `unwind_stack_1level()` is misused.
Marko Mikulicic 0:c0ecb8bf28eb 14035 */
Marko Mikulicic 0:c0ecb8bf28eb 14036 assert(call_frame != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 14037
Marko Mikulicic 0:c0ecb8bf28eb 14038 bcode_restore_registers(v7, call_frame->bcode, r);
Marko Mikulicic 0:c0ecb8bf28eb 14039 r->ops = call_frame->bcode_ops;
Marko Mikulicic 0:c0ecb8bf28eb 14040
Marko Mikulicic 0:c0ecb8bf28eb 14041 /*
Marko Mikulicic 0:c0ecb8bf28eb 14042 * restore thrown value if only there's no new thrown value
Marko Mikulicic 0:c0ecb8bf28eb 14043 * (otherwise, the new one overrides the previous one)
Marko Mikulicic 0:c0ecb8bf28eb 14044 */
Marko Mikulicic 0:c0ecb8bf28eb 14045 if (!v7->is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 14046 v7->vals.thrown_error = call_frame->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 14047 v7->is_thrown = call_frame->base.base.is_thrown;
Marko Mikulicic 0:c0ecb8bf28eb 14048 }
Marko Mikulicic 0:c0ecb8bf28eb 14049 }
Marko Mikulicic 0:c0ecb8bf28eb 14050 }
Marko Mikulicic 0:c0ecb8bf28eb 14051
Marko Mikulicic 0:c0ecb8bf28eb 14052 /*
Marko Mikulicic 0:c0ecb8bf28eb 14053 * Unwinds `call_stack` by 1 frame.
Marko Mikulicic 0:c0ecb8bf28eb 14054 *
Marko Mikulicic 0:c0ecb8bf28eb 14055 * Returns the type of the unwound frame
Marko Mikulicic 0:c0ecb8bf28eb 14056 */
Marko Mikulicic 0:c0ecb8bf28eb 14057 static v7_call_frame_mask_t unwind_stack_1level(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14058 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 14059 v7_call_frame_mask_t type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14060 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14061 fprintf(stderr, "unwinding stack by 1 level\n");
Marko Mikulicic 0:c0ecb8bf28eb 14062 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14063
Marko Mikulicic 0:c0ecb8bf28eb 14064 type_mask = v7->call_stack->type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14065
Marko Mikulicic 0:c0ecb8bf28eb 14066 /* drop the top frame */
Marko Mikulicic 0:c0ecb8bf28eb 14067 {
Marko Mikulicic 0:c0ecb8bf28eb 14068 struct v7_call_frame_base *tmp = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14069 v7->call_stack = v7->call_stack->prev;
Marko Mikulicic 0:c0ecb8bf28eb 14070 free(tmp);
Marko Mikulicic 0:c0ecb8bf28eb 14071 }
Marko Mikulicic 0:c0ecb8bf28eb 14072
Marko Mikulicic 0:c0ecb8bf28eb 14073 /*
Marko Mikulicic 0:c0ecb8bf28eb 14074 * depending on the unwound frame type, apply data from the top call frame(s)
Marko Mikulicic 0:c0ecb8bf28eb 14075 * which are still alive (if any)
Marko Mikulicic 0:c0ecb8bf28eb 14076 */
Marko Mikulicic 0:c0ecb8bf28eb 14077
Marko Mikulicic 0:c0ecb8bf28eb 14078 if (type_mask & V7_CALL_FRAME_MASK_PRIVATE) {
Marko Mikulicic 0:c0ecb8bf28eb 14079 apply_frame_private(v7, find_call_frame_private(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14080 }
Marko Mikulicic 0:c0ecb8bf28eb 14081
Marko Mikulicic 0:c0ecb8bf28eb 14082 if (type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 14083 apply_frame_bcode(v7, find_call_frame_bcode(v7), r);
Marko Mikulicic 0:c0ecb8bf28eb 14084 }
Marko Mikulicic 0:c0ecb8bf28eb 14085
Marko Mikulicic 0:c0ecb8bf28eb 14086 if (type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 14087 /* Nothing to do here at the moment */
Marko Mikulicic 0:c0ecb8bf28eb 14088 }
Marko Mikulicic 0:c0ecb8bf28eb 14089
Marko Mikulicic 0:c0ecb8bf28eb 14090 return type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14091 }
Marko Mikulicic 0:c0ecb8bf28eb 14092
Marko Mikulicic 0:c0ecb8bf28eb 14093 /*
Marko Mikulicic 0:c0ecb8bf28eb 14094 * Unwinds local "try stack" (i.e. local-to-current-function stack of nested
Marko Mikulicic 0:c0ecb8bf28eb 14095 * `try` blocks), looking for local-to-function blocks.
Marko Mikulicic 0:c0ecb8bf28eb 14096 *
Marko Mikulicic 0:c0ecb8bf28eb 14097 * Block types of interest are specified with `wanted_blocks_mask`: it's a
Marko Mikulicic 0:c0ecb8bf28eb 14098 * bitmask of `enum local_block` values.
Marko Mikulicic 0:c0ecb8bf28eb 14099 *
Marko Mikulicic 0:c0ecb8bf28eb 14100 * Only blocks of specified types will be considered, others will be dropped.
Marko Mikulicic 0:c0ecb8bf28eb 14101 *
Marko Mikulicic 0:c0ecb8bf28eb 14102 * If `restore_stack_size` is non-zero, the `v7->stack.len` will be restored
Marko Mikulicic 0:c0ecb8bf28eb 14103 * to the value saved when the block was created. This is useful when throwing,
Marko Mikulicic 0:c0ecb8bf28eb 14104 * since if we throw from the middle of the expression, the stack could have
Marko Mikulicic 0:c0ecb8bf28eb 14105 * any size. But you probably shouldn't set this flag when breaking and
Marko Mikulicic 0:c0ecb8bf28eb 14106 * returning, since it may hide real bugs in the opcode.
Marko Mikulicic 0:c0ecb8bf28eb 14107 *
Marko Mikulicic 0:c0ecb8bf28eb 14108 * Returns id of the block type that control was transferred into, or
Marko Mikulicic 0:c0ecb8bf28eb 14109 * `LOCAL_BLOCK_NONE` if no appropriate block was found. Note: returned value
Marko Mikulicic 0:c0ecb8bf28eb 14110 * contains at most 1 block bit; it can't contain multiple bits.
Marko Mikulicic 0:c0ecb8bf28eb 14111 */
Marko Mikulicic 0:c0ecb8bf28eb 14112 static enum local_block unwind_local_blocks_stack(
Marko Mikulicic 0:c0ecb8bf28eb 14113 struct v7 *v7, struct bcode_registers *r, unsigned int wanted_blocks_mask,
Marko Mikulicic 0:c0ecb8bf28eb 14114 uint8_t restore_stack_size) {
Marko Mikulicic 0:c0ecb8bf28eb 14115 val_t arr = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14116 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14117 enum local_block found_block = LOCAL_BLOCK_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 14118 unsigned long length;
Marko Mikulicic 0:c0ecb8bf28eb 14119
Marko Mikulicic 0:c0ecb8bf28eb 14120 tmp_stack_push(&tf, &arr);
Marko Mikulicic 0:c0ecb8bf28eb 14121
Marko Mikulicic 0:c0ecb8bf28eb 14122 arr = find_call_frame_private(v7)->vals.try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14123 if (v7_is_array(v7, arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 14124 /*
Marko Mikulicic 0:c0ecb8bf28eb 14125 * pop latest element from "try stack", loop until we need to transfer
Marko Mikulicic 0:c0ecb8bf28eb 14126 * control there
Marko Mikulicic 0:c0ecb8bf28eb 14127 */
Marko Mikulicic 0:c0ecb8bf28eb 14128 while ((length = v7_array_length(v7, arr)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 14129 /* get latest offset from the "try stack" */
Marko Mikulicic 0:c0ecb8bf28eb 14130 int64_t offset = v7_get_double(v7, v7_array_get(v7, arr, length - 1));
Marko Mikulicic 0:c0ecb8bf28eb 14131 enum local_block cur_block = LOCAL_BLOCK_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 14132
Marko Mikulicic 0:c0ecb8bf28eb 14133 /* get id of the current block type */
Marko Mikulicic 0:c0ecb8bf28eb 14134 switch (LBLOCK_TAG(offset)) {
Marko Mikulicic 0:c0ecb8bf28eb 14135 case LBLOCK_TAG_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 14136 cur_block = LOCAL_BLOCK_CATCH;
Marko Mikulicic 0:c0ecb8bf28eb 14137 break;
Marko Mikulicic 0:c0ecb8bf28eb 14138 case LBLOCK_TAG_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 14139 cur_block = LOCAL_BLOCK_FINALLY;
Marko Mikulicic 0:c0ecb8bf28eb 14140 break;
Marko Mikulicic 0:c0ecb8bf28eb 14141 case LBLOCK_TAG_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 14142 cur_block = LOCAL_BLOCK_LOOP;
Marko Mikulicic 0:c0ecb8bf28eb 14143 break;
Marko Mikulicic 0:c0ecb8bf28eb 14144 case LBLOCK_TAG_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 14145 cur_block = LOCAL_BLOCK_SWITCH;
Marko Mikulicic 0:c0ecb8bf28eb 14146 break;
Marko Mikulicic 0:c0ecb8bf28eb 14147 default:
Marko Mikulicic 0:c0ecb8bf28eb 14148 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14149 break;
Marko Mikulicic 0:c0ecb8bf28eb 14150 }
Marko Mikulicic 0:c0ecb8bf28eb 14151
Marko Mikulicic 0:c0ecb8bf28eb 14152 if (cur_block & wanted_blocks_mask) {
Marko Mikulicic 0:c0ecb8bf28eb 14153 /* need to transfer control to this offset */
Marko Mikulicic 0:c0ecb8bf28eb 14154 r->ops = r->bcode->ops.p + LBLOCK_OFFSET(offset);
Marko Mikulicic 0:c0ecb8bf28eb 14155 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14156 fprintf(stderr, "transferring to block #%d: %u\n", (int) cur_block,
Marko Mikulicic 0:c0ecb8bf28eb 14157 (unsigned int) LBLOCK_OFFSET(offset));
Marko Mikulicic 0:c0ecb8bf28eb 14158 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14159 found_block = cur_block;
Marko Mikulicic 0:c0ecb8bf28eb 14160 /* if needed, restore stack size to the saved value */
Marko Mikulicic 0:c0ecb8bf28eb 14161 if (restore_stack_size) {
Marko Mikulicic 0:c0ecb8bf28eb 14162 v7->stack.len = LBLOCK_STACK_SIZE(offset);
Marko Mikulicic 0:c0ecb8bf28eb 14163 }
Marko Mikulicic 0:c0ecb8bf28eb 14164 break;
Marko Mikulicic 0:c0ecb8bf28eb 14165 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14166 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14167 fprintf(stderr, "skipped block #%d: %u\n", (int) cur_block,
Marko Mikulicic 0:c0ecb8bf28eb 14168 (unsigned int) LBLOCK_OFFSET(offset));
Marko Mikulicic 0:c0ecb8bf28eb 14169 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14170 /*
Marko Mikulicic 0:c0ecb8bf28eb 14171 * since we don't need to control transfer there, just pop
Marko Mikulicic 0:c0ecb8bf28eb 14172 * it from the "try stack"
Marko Mikulicic 0:c0ecb8bf28eb 14173 */
Marko Mikulicic 0:c0ecb8bf28eb 14174 v7_array_del(v7, arr, length - 1);
Marko Mikulicic 0:c0ecb8bf28eb 14175 }
Marko Mikulicic 0:c0ecb8bf28eb 14176 }
Marko Mikulicic 0:c0ecb8bf28eb 14177 }
Marko Mikulicic 0:c0ecb8bf28eb 14178
Marko Mikulicic 0:c0ecb8bf28eb 14179 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14180 return found_block;
Marko Mikulicic 0:c0ecb8bf28eb 14181 }
Marko Mikulicic 0:c0ecb8bf28eb 14182
Marko Mikulicic 0:c0ecb8bf28eb 14183 /*
Marko Mikulicic 0:c0ecb8bf28eb 14184 * Perform break, if there is a `finally` block in effect, transfer
Marko Mikulicic 0:c0ecb8bf28eb 14185 * control there.
Marko Mikulicic 0:c0ecb8bf28eb 14186 */
Marko Mikulicic 0:c0ecb8bf28eb 14187 static void bcode_perform_break(struct v7 *v7, struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 14188 enum local_block found;
Marko Mikulicic 0:c0ecb8bf28eb 14189 unsigned int mask;
Marko Mikulicic 0:c0ecb8bf28eb 14190 v7->is_breaking = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14191 if (v7->is_continuing) {
Marko Mikulicic 0:c0ecb8bf28eb 14192 mask = LOCAL_BLOCK_LOOP;
Marko Mikulicic 0:c0ecb8bf28eb 14193 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14194 mask = LOCAL_BLOCK_LOOP | LOCAL_BLOCK_SWITCH;
Marko Mikulicic 0:c0ecb8bf28eb 14195 }
Marko Mikulicic 0:c0ecb8bf28eb 14196
Marko Mikulicic 0:c0ecb8bf28eb 14197 /*
Marko Mikulicic 0:c0ecb8bf28eb 14198 * Keep unwinding until we find local block of interest. We should not
Marko Mikulicic 0:c0ecb8bf28eb 14199 * encounter any "function" frames; only "private" frames are allowed.
Marko Mikulicic 0:c0ecb8bf28eb 14200 */
Marko Mikulicic 0:c0ecb8bf28eb 14201 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 14202 /*
Marko Mikulicic 0:c0ecb8bf28eb 14203 * Try to unwind local "try stack", considering only `finally` and `break`.
Marko Mikulicic 0:c0ecb8bf28eb 14204 */
Marko Mikulicic 0:c0ecb8bf28eb 14205 found = unwind_local_blocks_stack(v7, r, mask | LOCAL_BLOCK_FINALLY, 0);
Marko Mikulicic 0:c0ecb8bf28eb 14206 if (found == LOCAL_BLOCK_NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 14207 /*
Marko Mikulicic 0:c0ecb8bf28eb 14208 * no blocks found: this may happen if only the `break` or `continue` has
Marko Mikulicic 0:c0ecb8bf28eb 14209 * occurred inside "private" frame. So, unwind this frame, make sure it
Marko Mikulicic 0:c0ecb8bf28eb 14210 * is indeed a "private" frame, and keep unwinding local blocks.
Marko Mikulicic 0:c0ecb8bf28eb 14211 */
Marko Mikulicic 0:c0ecb8bf28eb 14212 v7_call_frame_mask_t frame_type_mask = unwind_stack_1level(v7, r);
Marko Mikulicic 0:c0ecb8bf28eb 14213 assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 14214 (void) frame_type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14215 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14216 /* found some block to transfer control into, stop unwinding */
Marko Mikulicic 0:c0ecb8bf28eb 14217 break;
Marko Mikulicic 0:c0ecb8bf28eb 14218 }
Marko Mikulicic 0:c0ecb8bf28eb 14219 }
Marko Mikulicic 0:c0ecb8bf28eb 14220
Marko Mikulicic 0:c0ecb8bf28eb 14221 /*
Marko Mikulicic 0:c0ecb8bf28eb 14222 * upon exit of a finally block we'll reenter here if is_breaking is true.
Marko Mikulicic 0:c0ecb8bf28eb 14223 * See OP_AFTER_FINALLY.
Marko Mikulicic 0:c0ecb8bf28eb 14224 */
Marko Mikulicic 0:c0ecb8bf28eb 14225 if (found == LOCAL_BLOCK_FINALLY) {
Marko Mikulicic 0:c0ecb8bf28eb 14226 v7->is_breaking = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14227 }
Marko Mikulicic 0:c0ecb8bf28eb 14228
Marko Mikulicic 0:c0ecb8bf28eb 14229 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 14230 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14231 }
Marko Mikulicic 0:c0ecb8bf28eb 14232
Marko Mikulicic 0:c0ecb8bf28eb 14233 /*
Marko Mikulicic 0:c0ecb8bf28eb 14234 * Perform return, but if there is a `finally` block in effect, transfer
Marko Mikulicic 0:c0ecb8bf28eb 14235 * control there.
Marko Mikulicic 0:c0ecb8bf28eb 14236 *
Marko Mikulicic 0:c0ecb8bf28eb 14237 * If `take_retval` is non-zero, value to return will be popped from stack
Marko Mikulicic 0:c0ecb8bf28eb 14238 * (and saved into `v7->vals.returned_value`), otherwise, it won't ae affected.
Marko Mikulicic 0:c0ecb8bf28eb 14239 */
Marko Mikulicic 0:c0ecb8bf28eb 14240 static enum v7_err bcode_perform_return(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14241 struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 14242 int take_retval) {
Marko Mikulicic 0:c0ecb8bf28eb 14243 /*
Marko Mikulicic 0:c0ecb8bf28eb 14244 * We should either take retval from the stack, or some value should already
Marko Mikulicic 0:c0ecb8bf28eb 14245 * de pending to return
Marko Mikulicic 0:c0ecb8bf28eb 14246 */
Marko Mikulicic 0:c0ecb8bf28eb 14247 assert(take_retval || v7->is_returned);
Marko Mikulicic 0:c0ecb8bf28eb 14248
Marko Mikulicic 0:c0ecb8bf28eb 14249 if (take_retval) {
Marko Mikulicic 0:c0ecb8bf28eb 14250 /* taking return value from stack */
Marko Mikulicic 0:c0ecb8bf28eb 14251 v7->vals.returned_value = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14252 v7->is_returned = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14253
Marko Mikulicic 0:c0ecb8bf28eb 14254 /*
Marko Mikulicic 0:c0ecb8bf28eb 14255 * returning (say, from `finally`) dismisses any errors that are eeing
Marko Mikulicic 0:c0ecb8bf28eb 14256 * thrown at the moment as well
Marko Mikulicic 0:c0ecb8bf28eb 14257 */
Marko Mikulicic 0:c0ecb8bf28eb 14258 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14259 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14260 }
Marko Mikulicic 0:c0ecb8bf28eb 14261
Marko Mikulicic 0:c0ecb8bf28eb 14262 /*
Marko Mikulicic 0:c0ecb8bf28eb 14263 * Keep unwinding until we unwound "function" frame, or found some `finally`
Marko Mikulicic 0:c0ecb8bf28eb 14264 * block.
Marko Mikulicic 0:c0ecb8bf28eb 14265 */
Marko Mikulicic 0:c0ecb8bf28eb 14266 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 14267 /* Try to unwind local "try stack", considering only `finally` blocks */
Marko Mikulicic 0:c0ecb8bf28eb 14268 if (unwind_local_blocks_stack(v7, r, (LOCAL_BLOCK_FINALLY), 0) ==
Marko Mikulicic 0:c0ecb8bf28eb 14269 LOCAL_BLOCK_NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 14270 /*
Marko Mikulicic 0:c0ecb8bf28eb 14271 * no `finally` blocks were found, so, unwind stack by 1 level, and see
Marko Mikulicic 0:c0ecb8bf28eb 14272 * if it's a "function" frame. If not, will keep unwinding.
Marko Mikulicic 0:c0ecb8bf28eb 14273 */
Marko Mikulicic 0:c0ecb8bf28eb 14274 if (unwind_stack_1level(v7, r) & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 14275 /*
Marko Mikulicic 0:c0ecb8bf28eb 14276 * unwound frame is a "function" frame, so, push returned value to
Marko Mikulicic 0:c0ecb8bf28eb 14277 * stack, and stop unwinding
Marko Mikulicic 0:c0ecb8bf28eb 14278 */
Marko Mikulicic 0:c0ecb8bf28eb 14279 PUSH(v7->vals.returned_value);
Marko Mikulicic 0:c0ecb8bf28eb 14280 v7->is_returned = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14281 v7->vals.returned_value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14282
Marko Mikulicic 0:c0ecb8bf28eb 14283 break;
Marko Mikulicic 0:c0ecb8bf28eb 14284 }
Marko Mikulicic 0:c0ecb8bf28eb 14285 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14286 /* found `finally` block, so, stop unwinding */
Marko Mikulicic 0:c0ecb8bf28eb 14287 break;
Marko Mikulicic 0:c0ecb8bf28eb 14288 }
Marko Mikulicic 0:c0ecb8bf28eb 14289 }
Marko Mikulicic 0:c0ecb8bf28eb 14290
Marko Mikulicic 0:c0ecb8bf28eb 14291 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 14292 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14293
Marko Mikulicic 0:c0ecb8bf28eb 14294 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14295 }
Marko Mikulicic 0:c0ecb8bf28eb 14296
Marko Mikulicic 0:c0ecb8bf28eb 14297 /*
Marko Mikulicic 0:c0ecb8bf28eb 14298 * Perform throw inside `eval_bcode()`.
Marko Mikulicic 0:c0ecb8bf28eb 14299 *
Marko Mikulicic 0:c0ecb8bf28eb 14300 * If `take_thrown_value` is non-zero, value to return will be popped from
Marko Mikulicic 0:c0ecb8bf28eb 14301 * stack (and saved into `v7->vals.thrown_error`), otherwise, it won't be
Marko Mikulicic 0:c0ecb8bf28eb 14302 * affected.
Marko Mikulicic 0:c0ecb8bf28eb 14303 *
Marko Mikulicic 0:c0ecb8bf28eb 14304 * Returns `V7_OK` if thrown exception was caught, `V7_EXEC_EXCEPTION`
Marko Mikulicic 0:c0ecb8bf28eb 14305 * otherwise (in this case, evaluation of current script must be stopped)
Marko Mikulicic 0:c0ecb8bf28eb 14306 *
Marko Mikulicic 0:c0ecb8bf28eb 14307 * When calling this function from `eval_rcode()`, you should wrap this call
Marko Mikulicic 0:c0ecb8bf28eb 14308 * into the `V7_TRY()` macro.
Marko Mikulicic 0:c0ecb8bf28eb 14309 */
Marko Mikulicic 0:c0ecb8bf28eb 14310 static enum v7_err bcode_perform_throw(struct v7 *v7, struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 14311 int take_thrown_value) {
Marko Mikulicic 0:c0ecb8bf28eb 14312 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14313 enum local_block found;
Marko Mikulicic 0:c0ecb8bf28eb 14314
Marko Mikulicic 0:c0ecb8bf28eb 14315 assert(take_thrown_value || v7->is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 14316
Marko Mikulicic 0:c0ecb8bf28eb 14317 if (take_thrown_value) {
Marko Mikulicic 0:c0ecb8bf28eb 14318 v7->vals.thrown_error = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14319 v7->is_thrown = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14320
Marko Mikulicic 0:c0ecb8bf28eb 14321 /* Throwing dismisses any pending return values */
Marko Mikulicic 0:c0ecb8bf28eb 14322 v7->is_returned = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14323 v7->vals.returned_value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14324 }
Marko Mikulicic 0:c0ecb8bf28eb 14325
Marko Mikulicic 0:c0ecb8bf28eb 14326 while ((found = unwind_local_blocks_stack(
Marko Mikulicic 0:c0ecb8bf28eb 14327 v7, r, (LOCAL_BLOCK_CATCH | LOCAL_BLOCK_FINALLY), 1)) ==
Marko Mikulicic 0:c0ecb8bf28eb 14328 LOCAL_BLOCK_NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 14329 if (v7->call_stack != v7->bottom_call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 14330 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14331 fprintf(stderr, "not at the bottom of the stack, going to unwind..\n");
Marko Mikulicic 0:c0ecb8bf28eb 14332 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14333 /* not reached bottom of the stack yet, keep unwinding */
Marko Mikulicic 0:c0ecb8bf28eb 14334 unwind_stack_1level(v7, r);
Marko Mikulicic 0:c0ecb8bf28eb 14335 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14336 /* reached stack bottom: uncaught exception */
Marko Mikulicic 0:c0ecb8bf28eb 14337 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14338 fprintf(stderr, "reached stack bottom: uncaught exception\n");
Marko Mikulicic 0:c0ecb8bf28eb 14339 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14340 rcode = V7_EXEC_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 14341 break;
Marko Mikulicic 0:c0ecb8bf28eb 14342 }
Marko Mikulicic 0:c0ecb8bf28eb 14343 }
Marko Mikulicic 0:c0ecb8bf28eb 14344
Marko Mikulicic 0:c0ecb8bf28eb 14345 if (found == LOCAL_BLOCK_CATCH) {
Marko Mikulicic 0:c0ecb8bf28eb 14346 /*
Marko Mikulicic 0:c0ecb8bf28eb 14347 * we're going to enter `catch` block, so, populate TOS with the thrown
Marko Mikulicic 0:c0ecb8bf28eb 14348 * value, and clear it in v7 context.
Marko Mikulicic 0:c0ecb8bf28eb 14349 */
Marko Mikulicic 0:c0ecb8bf28eb 14350 PUSH(v7->vals.thrown_error);
Marko Mikulicic 0:c0ecb8bf28eb 14351 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14352 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14353 }
Marko Mikulicic 0:c0ecb8bf28eb 14354
Marko Mikulicic 0:c0ecb8bf28eb 14355 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 14356 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14357
Marko Mikulicic 0:c0ecb8bf28eb 14358 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14359 }
Marko Mikulicic 0:c0ecb8bf28eb 14360
Marko Mikulicic 0:c0ecb8bf28eb 14361 /*
Marko Mikulicic 0:c0ecb8bf28eb 14362 * Throws reference error from `eval_bcode()`. Always wrap a call to this
Marko Mikulicic 0:c0ecb8bf28eb 14363 * function into `V7_TRY()`.
Marko Mikulicic 0:c0ecb8bf28eb 14364 */
Marko Mikulicic 0:c0ecb8bf28eb 14365 static enum v7_err bcode_throw_reference_error(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14366 struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 14367 val_t var_name) {
Marko Mikulicic 0:c0ecb8bf28eb 14368 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14369 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 14370 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 14371
Marko Mikulicic 0:c0ecb8bf28eb 14372 assert(v7_is_string(var_name));
Marko Mikulicic 0:c0ecb8bf28eb 14373 s = v7_get_string(v7, &var_name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 14374
Marko Mikulicic 0:c0ecb8bf28eb 14375 rcode = v7_throwf(v7, REFERENCE_ERROR, "[%.*s] is not defined",
Marko Mikulicic 0:c0ecb8bf28eb 14376 (int) name_len, s);
Marko Mikulicic 0:c0ecb8bf28eb 14377 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14378 return bcode_perform_throw(v7, r, 0);
Marko Mikulicic 0:c0ecb8bf28eb 14379 }
Marko Mikulicic 0:c0ecb8bf28eb 14380
Marko Mikulicic 0:c0ecb8bf28eb 14381 /*
Marko Mikulicic 0:c0ecb8bf28eb 14382 * Takes a half-done function (either from literal table or deserialized from
Marko Mikulicic 0:c0ecb8bf28eb 14383 * `ops` inlined data), and returns a ready-to-use function.
Marko Mikulicic 0:c0ecb8bf28eb 14384 *
Marko Mikulicic 0:c0ecb8bf28eb 14385 * The actual behaviour depends on whether the half-done function has
Marko Mikulicic 0:c0ecb8bf28eb 14386 * `prototype` defined. If there's no prototype (i.e. it's `undefined`), then
Marko Mikulicic 0:c0ecb8bf28eb 14387 * the new function is created, with bcode from a given one. If, however,
Marko Mikulicic 0:c0ecb8bf28eb 14388 * the prototype is defined, it means that the function was just deserialized
Marko Mikulicic 0:c0ecb8bf28eb 14389 * from `ops`, so we only need to set `scope` on it.
Marko Mikulicic 0:c0ecb8bf28eb 14390 *
Marko Mikulicic 0:c0ecb8bf28eb 14391 * Assumes `func` is owned by the caller.
Marko Mikulicic 0:c0ecb8bf28eb 14392 */
Marko Mikulicic 0:c0ecb8bf28eb 14393 static val_t bcode_instantiate_function(struct v7 *v7, val_t func) {
Marko Mikulicic 0:c0ecb8bf28eb 14394 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 14395 struct v7_generic_object *scope;
Marko Mikulicic 0:c0ecb8bf28eb 14396 struct v7_js_function *f;
Marko Mikulicic 0:c0ecb8bf28eb 14397 assert(is_js_function(func));
Marko Mikulicic 0:c0ecb8bf28eb 14398 f = get_js_function_struct(func);
Marko Mikulicic 0:c0ecb8bf28eb 14399
Marko Mikulicic 0:c0ecb8bf28eb 14400 scope = get_generic_object_struct(get_scope(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14401
Marko Mikulicic 0:c0ecb8bf28eb 14402 if (v7_is_undefined(v7_get(v7, func, "prototype", 9))) {
Marko Mikulicic 0:c0ecb8bf28eb 14403 /*
Marko Mikulicic 0:c0ecb8bf28eb 14404 * Function's `prototype` is `undefined`: it means that the function is
Marko Mikulicic 0:c0ecb8bf28eb 14405 * created by the compiler and is stored in the literal table. We have to
Marko Mikulicic 0:c0ecb8bf28eb 14406 * create completely new function
Marko Mikulicic 0:c0ecb8bf28eb 14407 */
Marko Mikulicic 0:c0ecb8bf28eb 14408 struct v7_js_function *rf;
Marko Mikulicic 0:c0ecb8bf28eb 14409
Marko Mikulicic 0:c0ecb8bf28eb 14410 res = mk_js_function(v7, scope, v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14411
Marko Mikulicic 0:c0ecb8bf28eb 14412 /* Copy and retain bcode */
Marko Mikulicic 0:c0ecb8bf28eb 14413 rf = get_js_function_struct(res);
Marko Mikulicic 0:c0ecb8bf28eb 14414 rf->bcode = f->bcode;
Marko Mikulicic 0:c0ecb8bf28eb 14415 retain_bcode(v7, rf->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 14416 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14417 /*
Marko Mikulicic 0:c0ecb8bf28eb 14418 * Function's `prototype` is NOT `undefined`: it means that the function is
Marko Mikulicic 0:c0ecb8bf28eb 14419 * deserialized from inline `ops` data, and we just need to set scope on
Marko Mikulicic 0:c0ecb8bf28eb 14420 * it.
Marko Mikulicic 0:c0ecb8bf28eb 14421 */
Marko Mikulicic 0:c0ecb8bf28eb 14422 res = func;
Marko Mikulicic 0:c0ecb8bf28eb 14423 f->scope = scope;
Marko Mikulicic 0:c0ecb8bf28eb 14424 }
Marko Mikulicic 0:c0ecb8bf28eb 14425
Marko Mikulicic 0:c0ecb8bf28eb 14426 return res;
Marko Mikulicic 0:c0ecb8bf28eb 14427 }
Marko Mikulicic 0:c0ecb8bf28eb 14428
Marko Mikulicic 0:c0ecb8bf28eb 14429 /**
Marko Mikulicic 0:c0ecb8bf28eb 14430 * Call C function `func` with given `this_object` and array of arguments
Marko Mikulicic 0:c0ecb8bf28eb 14431 * `args`. `func` should be a C function pointer, not C function object.
Marko Mikulicic 0:c0ecb8bf28eb 14432 */
Marko Mikulicic 0:c0ecb8bf28eb 14433 static enum v7_err call_cfunction(struct v7 *v7, val_t func, val_t this_object,
Marko Mikulicic 0:c0ecb8bf28eb 14434 val_t args, uint8_t is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 14435 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 14436 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14437 uint8_t saved_inhibit_gc = v7->inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 14438 val_t saved_arguments = v7->vals.arguments;
Marko Mikulicic 0:c0ecb8bf28eb 14439 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14440 v7_cfunction_t *cfunc = get_cfunction_ptr(v7, func);
Marko Mikulicic 0:c0ecb8bf28eb 14441
Marko Mikulicic 0:c0ecb8bf28eb 14442 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14443
Marko Mikulicic 0:c0ecb8bf28eb 14444 tmp_stack_push(&tf, &saved_arguments);
Marko Mikulicic 0:c0ecb8bf28eb 14445
Marko Mikulicic 0:c0ecb8bf28eb 14446 append_call_frame_cfunc(v7, this_object, cfunc);
Marko Mikulicic 0:c0ecb8bf28eb 14447
Marko Mikulicic 0:c0ecb8bf28eb 14448 /*
Marko Mikulicic 0:c0ecb8bf28eb 14449 * prepare cfunction environment
Marko Mikulicic 0:c0ecb8bf28eb 14450 */
Marko Mikulicic 0:c0ecb8bf28eb 14451 v7->inhibit_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14452 v7->vals.arguments = args;
Marko Mikulicic 0:c0ecb8bf28eb 14453
Marko Mikulicic 0:c0ecb8bf28eb 14454 /* call C function */
Marko Mikulicic 0:c0ecb8bf28eb 14455 rcode = cfunc(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 14456 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 14457 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 14458 }
Marko Mikulicic 0:c0ecb8bf28eb 14459
Marko Mikulicic 0:c0ecb8bf28eb 14460 if (is_constructor && !v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 14461 /* constructor returned non-object: replace it with `this` */
Marko Mikulicic 0:c0ecb8bf28eb 14462 *res = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14463 }
Marko Mikulicic 0:c0ecb8bf28eb 14464
Marko Mikulicic 0:c0ecb8bf28eb 14465 clean:
Marko Mikulicic 0:c0ecb8bf28eb 14466 v7->vals.arguments = saved_arguments;
Marko Mikulicic 0:c0ecb8bf28eb 14467 v7->inhibit_gc = saved_inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 14468
Marko Mikulicic 0:c0ecb8bf28eb 14469 unwind_stack_1level(v7, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 14470
Marko Mikulicic 0:c0ecb8bf28eb 14471 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14472 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14473 }
Marko Mikulicic 0:c0ecb8bf28eb 14474
Marko Mikulicic 0:c0ecb8bf28eb 14475 /*
Marko Mikulicic 0:c0ecb8bf28eb 14476 * Evaluate `OP_TRY_PUSH_CATCH` or `OP_TRY_PUSH_FINALLY`: Take an offset (from
Marko Mikulicic 0:c0ecb8bf28eb 14477 * the parameter of opcode) and push it onto "try stack"
Marko Mikulicic 0:c0ecb8bf28eb 14478 */
Marko Mikulicic 0:c0ecb8bf28eb 14479 static void eval_try_push(struct v7 *v7, enum opcode op,
Marko Mikulicic 0:c0ecb8bf28eb 14480 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 14481 val_t arr = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14482 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14483 bcode_off_t target;
Marko Mikulicic 0:c0ecb8bf28eb 14484 int64_t offset_tag = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14485
Marko Mikulicic 0:c0ecb8bf28eb 14486 tmp_stack_push(&tf, &arr);
Marko Mikulicic 0:c0ecb8bf28eb 14487
Marko Mikulicic 0:c0ecb8bf28eb 14488 /* make sure "try stack" array exists */
Marko Mikulicic 0:c0ecb8bf28eb 14489 arr = find_call_frame_private(v7)->vals.try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14490 if (!v7_is_array(v7, arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 14491 arr = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14492 find_call_frame_private(v7)->vals.try_stack = arr;
Marko Mikulicic 0:c0ecb8bf28eb 14493 }
Marko Mikulicic 0:c0ecb8bf28eb 14494
Marko Mikulicic 0:c0ecb8bf28eb 14495 /*
Marko Mikulicic 0:c0ecb8bf28eb 14496 * push the target address at the end of the "try stack" array
Marko Mikulicic 0:c0ecb8bf28eb 14497 */
Marko Mikulicic 0:c0ecb8bf28eb 14498 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14499 case OP_TRY_PUSH_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 14500 offset_tag = LBLOCK_TAG_CATCH;
Marko Mikulicic 0:c0ecb8bf28eb 14501 break;
Marko Mikulicic 0:c0ecb8bf28eb 14502 case OP_TRY_PUSH_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 14503 offset_tag = LBLOCK_TAG_FINALLY;
Marko Mikulicic 0:c0ecb8bf28eb 14504 break;
Marko Mikulicic 0:c0ecb8bf28eb 14505 case OP_TRY_PUSH_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 14506 offset_tag = LBLOCK_TAG_LOOP;
Marko Mikulicic 0:c0ecb8bf28eb 14507 break;
Marko Mikulicic 0:c0ecb8bf28eb 14508 case OP_TRY_PUSH_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 14509 offset_tag = LBLOCK_TAG_SWITCH;
Marko Mikulicic 0:c0ecb8bf28eb 14510 break;
Marko Mikulicic 0:c0ecb8bf28eb 14511 default:
Marko Mikulicic 0:c0ecb8bf28eb 14512 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14513 break;
Marko Mikulicic 0:c0ecb8bf28eb 14514 }
Marko Mikulicic 0:c0ecb8bf28eb 14515 target = bcode_get_target(&r->ops);
Marko Mikulicic 0:c0ecb8bf28eb 14516 v7_array_push(v7, arr, v7_mk_number(v7, LBLOCK_ITEM_CREATE(target, offset_tag,
Marko Mikulicic 0:c0ecb8bf28eb 14517 v7->stack.len)));
Marko Mikulicic 0:c0ecb8bf28eb 14518
Marko Mikulicic 0:c0ecb8bf28eb 14519 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14520 }
Marko Mikulicic 0:c0ecb8bf28eb 14521
Marko Mikulicic 0:c0ecb8bf28eb 14522 /*
Marko Mikulicic 0:c0ecb8bf28eb 14523 * Evaluate `OP_TRY_POP`: just pop latest item from "try stack", ignoring it
Marko Mikulicic 0:c0ecb8bf28eb 14524 */
Marko Mikulicic 0:c0ecb8bf28eb 14525 static enum v7_err eval_try_pop(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 14526 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14527 val_t arr = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14528 unsigned long length;
Marko Mikulicic 0:c0ecb8bf28eb 14529 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14530
Marko Mikulicic 0:c0ecb8bf28eb 14531 tmp_stack_push(&tf, &arr);
Marko Mikulicic 0:c0ecb8bf28eb 14532
Marko Mikulicic 0:c0ecb8bf28eb 14533 /* get "try stack" array, which must be defined and must not be emtpy */
Marko Mikulicic 0:c0ecb8bf28eb 14534 arr = find_call_frame_private(v7)->vals.try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14535 if (!v7_is_array(v7, arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 14536 rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is not an array");
Marko Mikulicic 0:c0ecb8bf28eb 14537 V7_TRY(V7_INTERNAL_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 14538 }
Marko Mikulicic 0:c0ecb8bf28eb 14539
Marko Mikulicic 0:c0ecb8bf28eb 14540 length = v7_array_length(v7, arr);
Marko Mikulicic 0:c0ecb8bf28eb 14541 if (length == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 14542 rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is empty");
Marko Mikulicic 0:c0ecb8bf28eb 14543 V7_TRY(V7_INTERNAL_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 14544 }
Marko Mikulicic 0:c0ecb8bf28eb 14545
Marko Mikulicic 0:c0ecb8bf28eb 14546 /* delete the latest element of this array */
Marko Mikulicic 0:c0ecb8bf28eb 14547 v7_array_del(v7, arr, length - 1);
Marko Mikulicic 0:c0ecb8bf28eb 14548
Marko Mikulicic 0:c0ecb8bf28eb 14549 clean:
Marko Mikulicic 0:c0ecb8bf28eb 14550 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14551 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14552 }
Marko Mikulicic 0:c0ecb8bf28eb 14553
Marko Mikulicic 0:c0ecb8bf28eb 14554 static void own_bcode(struct v7 *v7, struct bcode *p) {
Marko Mikulicic 0:c0ecb8bf28eb 14555 mbuf_append(&v7->act_bcodes, &p, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 14556 }
Marko Mikulicic 0:c0ecb8bf28eb 14557
Marko Mikulicic 0:c0ecb8bf28eb 14558 static void disown_bcode(struct v7 *v7, struct bcode *p) {
Marko Mikulicic 0:c0ecb8bf28eb 14559 #ifndef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 14560 struct bcode **vp =
Marko Mikulicic 0:c0ecb8bf28eb 14561 (struct bcode **) (v7->act_bcodes.buf + v7->act_bcodes.len - sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 14562
Marko Mikulicic 0:c0ecb8bf28eb 14563 /* given `p` should be the last item */
Marko Mikulicic 0:c0ecb8bf28eb 14564 assert(*vp == p);
Marko Mikulicic 0:c0ecb8bf28eb 14565 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14566 v7->act_bcodes.len -= sizeof(p);
Marko Mikulicic 0:c0ecb8bf28eb 14567 }
Marko Mikulicic 0:c0ecb8bf28eb 14568
Marko Mikulicic 0:c0ecb8bf28eb 14569 /* Keeps track of last evaluated bcodes in order to improve error reporting */
Marko Mikulicic 0:c0ecb8bf28eb 14570 static void push_bcode_history(struct v7 *v7, enum opcode op) {
Marko Mikulicic 0:c0ecb8bf28eb 14571 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 14572
Marko Mikulicic 0:c0ecb8bf28eb 14573 if (op == OP_CHECK_CALL || op == OP_CALL || op == OP_NEW) return;
Marko Mikulicic 0:c0ecb8bf28eb 14574
Marko Mikulicic 0:c0ecb8bf28eb 14575 for (i = ARRAY_SIZE(v7->last_ops) - 1; i > 0; i--) {
Marko Mikulicic 0:c0ecb8bf28eb 14576 v7->last_ops[i] = v7->last_ops[i - 1];
Marko Mikulicic 0:c0ecb8bf28eb 14577 }
Marko Mikulicic 0:c0ecb8bf28eb 14578 v7->last_ops[0] = op;
Marko Mikulicic 0:c0ecb8bf28eb 14579 }
Marko Mikulicic 0:c0ecb8bf28eb 14580
Marko Mikulicic 0:c0ecb8bf28eb 14581 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 14582 static void reset_last_name(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 14583 v7->vals.last_name[0] = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14584 v7->vals.last_name[1] = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14585 }
Marko Mikulicic 0:c0ecb8bf28eb 14586 #else
Marko Mikulicic 0:c0ecb8bf28eb 14587 static void reset_last_name(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 14588 /* should be inlined out */
Marko Mikulicic 0:c0ecb8bf28eb 14589 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 14590 }
Marko Mikulicic 0:c0ecb8bf28eb 14591 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14592
Marko Mikulicic 0:c0ecb8bf28eb 14593 static void prop_iter_ctx_dtor(struct v7 *v7, void *ud) {
Marko Mikulicic 0:c0ecb8bf28eb 14594 struct prop_iter_ctx *ctx = (struct prop_iter_ctx *) ud;
Marko Mikulicic 0:c0ecb8bf28eb 14595 v7_destruct_prop_iter_ctx(v7, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 14596 free(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 14597 }
Marko Mikulicic 0:c0ecb8bf28eb 14598
Marko Mikulicic 0:c0ecb8bf28eb 14599 /*
Marko Mikulicic 0:c0ecb8bf28eb 14600 * Evaluates given `bcode`. If `reset_line_no` is non-zero, the line number
Marko Mikulicic 0:c0ecb8bf28eb 14601 * is initially reset to 1; otherwise, it is inherited from the previous call
Marko Mikulicic 0:c0ecb8bf28eb 14602 * frame.
Marko Mikulicic 0:c0ecb8bf28eb 14603 */
Marko Mikulicic 0:c0ecb8bf28eb 14604 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 14605 V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 14606 val_t this_object, uint8_t reset_line_no,
Marko Mikulicic 0:c0ecb8bf28eb 14607 val_t *_res) {
Marko Mikulicic 0:c0ecb8bf28eb 14608 struct bcode_registers r;
Marko Mikulicic 0:c0ecb8bf28eb 14609 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14610 struct v7_call_frame_base *saved_bottom_call_frame = v7->bottom_call_frame;
Marko Mikulicic 0:c0ecb8bf28eb 14611
Marko Mikulicic 0:c0ecb8bf28eb 14612 /*
Marko Mikulicic 0:c0ecb8bf28eb 14613 * Dummy variable just to enforce that `BTRY()` macro is used only inside the
Marko Mikulicic 0:c0ecb8bf28eb 14614 * `eval_bcode()` function
Marko Mikulicic 0:c0ecb8bf28eb 14615 */
Marko Mikulicic 0:c0ecb8bf28eb 14616 uint8_t _you_should_use_BTRY_in_eval_bcode_only = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14617
Marko Mikulicic 0:c0ecb8bf28eb 14618 char buf[512];
Marko Mikulicic 0:c0ecb8bf28eb 14619
Marko Mikulicic 0:c0ecb8bf28eb 14620 val_t res = V7_UNDEFINED, v1 = V7_UNDEFINED, v2 = V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 14621 v3 = V7_UNDEFINED, v4 = V7_UNDEFINED, scope_frame = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14622 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14623
Marko Mikulicic 0:c0ecb8bf28eb 14624 append_call_frame_bcode(v7, NULL, bcode, this_object, get_scope(v7), 0);
Marko Mikulicic 0:c0ecb8bf28eb 14625
Marko Mikulicic 0:c0ecb8bf28eb 14626 if (reset_line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 14627 v7->call_stack->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14628 }
Marko Mikulicic 0:c0ecb8bf28eb 14629
Marko Mikulicic 0:c0ecb8bf28eb 14630 /*
Marko Mikulicic 0:c0ecb8bf28eb 14631 * Set current call stack as the "bottom" call stack, so that bcode evaluator
Marko Mikulicic 0:c0ecb8bf28eb 14632 * will exit when it reaches this "bottom"
Marko Mikulicic 0:c0ecb8bf28eb 14633 */
Marko Mikulicic 0:c0ecb8bf28eb 14634 v7->bottom_call_frame = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14635
Marko Mikulicic 0:c0ecb8bf28eb 14636 bcode_restore_registers(v7, bcode, &r);
Marko Mikulicic 0:c0ecb8bf28eb 14637
Marko Mikulicic 0:c0ecb8bf28eb 14638 tmp_stack_push(&tf, &res);
Marko Mikulicic 0:c0ecb8bf28eb 14639 tmp_stack_push(&tf, &v1);
Marko Mikulicic 0:c0ecb8bf28eb 14640 tmp_stack_push(&tf, &v2);
Marko Mikulicic 0:c0ecb8bf28eb 14641 tmp_stack_push(&tf, &v3);
Marko Mikulicic 0:c0ecb8bf28eb 14642 tmp_stack_push(&tf, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 14643 tmp_stack_push(&tf, &scope_frame);
Marko Mikulicic 0:c0ecb8bf28eb 14644
Marko Mikulicic 0:c0ecb8bf28eb 14645 /*
Marko Mikulicic 0:c0ecb8bf28eb 14646 * populate local variables on current scope, making them undeletable
Marko Mikulicic 0:c0ecb8bf28eb 14647 * (since they're defined with `var`)
Marko Mikulicic 0:c0ecb8bf28eb 14648 */
Marko Mikulicic 0:c0ecb8bf28eb 14649 {
Marko Mikulicic 0:c0ecb8bf28eb 14650 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 14651 for (i = 0; i < bcode->names_cnt; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 14652 r.ops = bcode_next_name_v(v7, bcode, r.ops, &v1);
Marko Mikulicic 0:c0ecb8bf28eb 14653
Marko Mikulicic 0:c0ecb8bf28eb 14654 /* set undeletable property on current scope */
Marko Mikulicic 0:c0ecb8bf28eb 14655 V7_TRY(def_property_v(v7, get_scope(v7), v1, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 14656 V7_UNDEFINED, 1 /*as_assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14657 }
Marko Mikulicic 0:c0ecb8bf28eb 14658 }
Marko Mikulicic 0:c0ecb8bf28eb 14659
Marko Mikulicic 0:c0ecb8bf28eb 14660 restart:
Marko Mikulicic 0:c0ecb8bf28eb 14661 while (r.ops < r.end && rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 14662 enum opcode op = (enum opcode) * r.ops;
Marko Mikulicic 0:c0ecb8bf28eb 14663
Marko Mikulicic 0:c0ecb8bf28eb 14664 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 14665 if ((uint8_t) op >= _OP_LINE_NO) {
Marko Mikulicic 0:c0ecb8bf28eb 14666 unsigned char buf[sizeof(size_t)];
Marko Mikulicic 0:c0ecb8bf28eb 14667 int len;
Marko Mikulicic 0:c0ecb8bf28eb 14668 size_t max_llen = sizeof(buf);
Marko Mikulicic 0:c0ecb8bf28eb 14669
Marko Mikulicic 0:c0ecb8bf28eb 14670 /* ASAN doesn't like out of bound reads */
Marko Mikulicic 0:c0ecb8bf28eb 14671 if (r.ops + max_llen > r.end) {
Marko Mikulicic 0:c0ecb8bf28eb 14672 max_llen = r.end - r.ops;
Marko Mikulicic 0:c0ecb8bf28eb 14673 }
Marko Mikulicic 0:c0ecb8bf28eb 14674
Marko Mikulicic 0:c0ecb8bf28eb 14675 /*
Marko Mikulicic 0:c0ecb8bf28eb 14676 * before we decode varint, we'll have to swap MSB and LSB, but we can't
Marko Mikulicic 0:c0ecb8bf28eb 14677 * do it in place since we're decoding from constant memory, so, we also
Marko Mikulicic 0:c0ecb8bf28eb 14678 * have to copy the data to the temp buffer first. 4 bytes should be
Marko Mikulicic 0:c0ecb8bf28eb 14679 * enough for everyone's line number.
Marko Mikulicic 0:c0ecb8bf28eb 14680 */
Marko Mikulicic 0:c0ecb8bf28eb 14681 memcpy(buf, r.ops, max_llen);
Marko Mikulicic 0:c0ecb8bf28eb 14682 buf[0] = msb_lsb_swap(buf[0]);
Marko Mikulicic 0:c0ecb8bf28eb 14683
Marko Mikulicic 0:c0ecb8bf28eb 14684 v7->call_stack->line_no = decode_varint(buf, &len) >> 1;
Marko Mikulicic 0:c0ecb8bf28eb 14685 assert((size_t) len <= sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 14686 r.ops += len;
Marko Mikulicic 0:c0ecb8bf28eb 14687
Marko Mikulicic 0:c0ecb8bf28eb 14688 continue;
Marko Mikulicic 0:c0ecb8bf28eb 14689 }
Marko Mikulicic 0:c0ecb8bf28eb 14690 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14691
Marko Mikulicic 0:c0ecb8bf28eb 14692 push_bcode_history(v7, op);
Marko Mikulicic 0:c0ecb8bf28eb 14693
Marko Mikulicic 0:c0ecb8bf28eb 14694 if (v7->need_gc) {
Marko Mikulicic 0:c0ecb8bf28eb 14695 if (maybe_gc(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 14696 v7->need_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14697 }
Marko Mikulicic 0:c0ecb8bf28eb 14698 }
Marko Mikulicic 0:c0ecb8bf28eb 14699
Marko Mikulicic 0:c0ecb8bf28eb 14700 r.need_inc_ops = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14701 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14702 {
Marko Mikulicic 0:c0ecb8bf28eb 14703 char *dops = r.ops;
Marko Mikulicic 0:c0ecb8bf28eb 14704 fprintf(stderr, "eval ");
Marko Mikulicic 0:c0ecb8bf28eb 14705 dump_op(v7, stderr, r.bcode, &dops);
Marko Mikulicic 0:c0ecb8bf28eb 14706 }
Marko Mikulicic 0:c0ecb8bf28eb 14707 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14708
Marko Mikulicic 0:c0ecb8bf28eb 14709 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14710 case OP_DROP:
Marko Mikulicic 0:c0ecb8bf28eb 14711 POP();
Marko Mikulicic 0:c0ecb8bf28eb 14712 break;
Marko Mikulicic 0:c0ecb8bf28eb 14713 case OP_DUP:
Marko Mikulicic 0:c0ecb8bf28eb 14714 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14715 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14716 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14717 break;
Marko Mikulicic 0:c0ecb8bf28eb 14718 case OP_2DUP:
Marko Mikulicic 0:c0ecb8bf28eb 14719 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14720 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14721 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14722 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 14723 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14724 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 14725 break;
Marko Mikulicic 0:c0ecb8bf28eb 14726 case OP_SWAP:
Marko Mikulicic 0:c0ecb8bf28eb 14727 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14728 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14729 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14730 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 14731 break;
Marko Mikulicic 0:c0ecb8bf28eb 14732 case OP_STASH:
Marko Mikulicic 0:c0ecb8bf28eb 14733 assert(!v7->is_stashed);
Marko Mikulicic 0:c0ecb8bf28eb 14734 v7->vals.stash = TOS();
Marko Mikulicic 0:c0ecb8bf28eb 14735 v7->is_stashed = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14736 break;
Marko Mikulicic 0:c0ecb8bf28eb 14737 case OP_UNSTASH:
Marko Mikulicic 0:c0ecb8bf28eb 14738 assert(v7->is_stashed);
Marko Mikulicic 0:c0ecb8bf28eb 14739 POP();
Marko Mikulicic 0:c0ecb8bf28eb 14740 PUSH(v7->vals.stash);
Marko Mikulicic 0:c0ecb8bf28eb 14741 v7->vals.stash = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14742 v7->is_stashed = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14743 break;
Marko Mikulicic 0:c0ecb8bf28eb 14744
Marko Mikulicic 0:c0ecb8bf28eb 14745 case OP_SWAP_DROP:
Marko Mikulicic 0:c0ecb8bf28eb 14746 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14747 POP();
Marko Mikulicic 0:c0ecb8bf28eb 14748 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14749 break;
Marko Mikulicic 0:c0ecb8bf28eb 14750
Marko Mikulicic 0:c0ecb8bf28eb 14751 case OP_PUSH_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 14752 PUSH(V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 14753 break;
Marko Mikulicic 0:c0ecb8bf28eb 14754 case OP_PUSH_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 14755 PUSH(V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 14756 break;
Marko Mikulicic 0:c0ecb8bf28eb 14757 case OP_PUSH_THIS:
Marko Mikulicic 0:c0ecb8bf28eb 14758 PUSH(v7_get_this(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14759 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14760 break;
Marko Mikulicic 0:c0ecb8bf28eb 14761 case OP_PUSH_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 14762 PUSH(v7_mk_boolean(v7, 1));
Marko Mikulicic 0:c0ecb8bf28eb 14763 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14764 break;
Marko Mikulicic 0:c0ecb8bf28eb 14765 case OP_PUSH_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 14766 PUSH(v7_mk_boolean(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 14767 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14768 break;
Marko Mikulicic 0:c0ecb8bf28eb 14769 case OP_PUSH_ZERO:
Marko Mikulicic 0:c0ecb8bf28eb 14770 PUSH(v7_mk_number(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 14771 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14772 break;
Marko Mikulicic 0:c0ecb8bf28eb 14773 case OP_PUSH_ONE:
Marko Mikulicic 0:c0ecb8bf28eb 14774 PUSH(v7_mk_number(v7, 1));
Marko Mikulicic 0:c0ecb8bf28eb 14775 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14776 break;
Marko Mikulicic 0:c0ecb8bf28eb 14777 case OP_PUSH_LIT: {
Marko Mikulicic 0:c0ecb8bf28eb 14778 PUSH(bcode_decode_lit(v7, r.bcode, &r.ops));
Marko Mikulicic 0:c0ecb8bf28eb 14779 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 14780 /* name tracking */
Marko Mikulicic 0:c0ecb8bf28eb 14781 if (!v7_is_string(TOS())) {
Marko Mikulicic 0:c0ecb8bf28eb 14782 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14783 }
Marko Mikulicic 0:c0ecb8bf28eb 14784 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14785 break;
Marko Mikulicic 0:c0ecb8bf28eb 14786 }
Marko Mikulicic 0:c0ecb8bf28eb 14787 case OP_LOGICAL_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 14788 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14789 PUSH(v7_mk_boolean(v7, !v7_is_truthy(v7, v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14790 break;
Marko Mikulicic 0:c0ecb8bf28eb 14791 case OP_NOT: {
Marko Mikulicic 0:c0ecb8bf28eb 14792 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14793 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14794 PUSH(v7_mk_number(v7, ~(int32_t) v7_get_double(v7, v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14795 break;
Marko Mikulicic 0:c0ecb8bf28eb 14796 }
Marko Mikulicic 0:c0ecb8bf28eb 14797 case OP_NEG: {
Marko Mikulicic 0:c0ecb8bf28eb 14798 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14799 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14800 PUSH(v7_mk_number(v7, -v7_get_double(v7, v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14801 break;
Marko Mikulicic 0:c0ecb8bf28eb 14802 }
Marko Mikulicic 0:c0ecb8bf28eb 14803 case OP_POS: {
Marko Mikulicic 0:c0ecb8bf28eb 14804 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14805 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14806 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14807 break;
Marko Mikulicic 0:c0ecb8bf28eb 14808 }
Marko Mikulicic 0:c0ecb8bf28eb 14809 case OP_ADD: {
Marko Mikulicic 0:c0ecb8bf28eb 14810 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14811 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14812
Marko Mikulicic 0:c0ecb8bf28eb 14813 /*
Marko Mikulicic 0:c0ecb8bf28eb 14814 * If either operand is an object, convert both of them to primitives
Marko Mikulicic 0:c0ecb8bf28eb 14815 */
Marko Mikulicic 0:c0ecb8bf28eb 14816 if (v7_is_object(v1) || v7_is_object(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14817 BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_AUTO, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14818 BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_AUTO, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14819 }
Marko Mikulicic 0:c0ecb8bf28eb 14820
Marko Mikulicic 0:c0ecb8bf28eb 14821 if (v7_is_string(v1) || v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14822 /* Convert both operands to strings, and concatenate */
Marko Mikulicic 0:c0ecb8bf28eb 14823
Marko Mikulicic 0:c0ecb8bf28eb 14824 BTRY(primitive_to_str(v7, v1, &v1, NULL, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14825 BTRY(primitive_to_str(v7, v2, &v2, NULL, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14826
Marko Mikulicic 0:c0ecb8bf28eb 14827 PUSH(s_concat(v7, v1, v2));
Marko Mikulicic 0:c0ecb8bf28eb 14828 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14829 /* Convert both operands to numbers, and sum */
Marko Mikulicic 0:c0ecb8bf28eb 14830
Marko Mikulicic 0:c0ecb8bf28eb 14831 BTRY(primitive_to_number(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14832 BTRY(primitive_to_number(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14833
Marko Mikulicic 0:c0ecb8bf28eb 14834 PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14835 v7_get_double(v7, v2))));
Marko Mikulicic 0:c0ecb8bf28eb 14836 }
Marko Mikulicic 0:c0ecb8bf28eb 14837 break;
Marko Mikulicic 0:c0ecb8bf28eb 14838 }
Marko Mikulicic 0:c0ecb8bf28eb 14839 case OP_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 14840 case OP_REM:
Marko Mikulicic 0:c0ecb8bf28eb 14841 case OP_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 14842 case OP_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 14843 case OP_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 14844 case OP_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 14845 case OP_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 14846 case OP_OR:
Marko Mikulicic 0:c0ecb8bf28eb 14847 case OP_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 14848 case OP_AND: {
Marko Mikulicic 0:c0ecb8bf28eb 14849 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14850 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14851
Marko Mikulicic 0:c0ecb8bf28eb 14852 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14853 BTRY(to_number_v(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14854
Marko Mikulicic 0:c0ecb8bf28eb 14855 PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14856 v7_get_double(v7, v2))));
Marko Mikulicic 0:c0ecb8bf28eb 14857 break;
Marko Mikulicic 0:c0ecb8bf28eb 14858 }
Marko Mikulicic 0:c0ecb8bf28eb 14859 case OP_EQ_EQ: {
Marko Mikulicic 0:c0ecb8bf28eb 14860 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14861 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14862 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14863 res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) == 0);
Marko Mikulicic 0:c0ecb8bf28eb 14864 } else if (v1 == v2 && v1 == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 14865 res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 14866 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14867 res = v7_mk_boolean(v7, v1 == v2);
Marko Mikulicic 0:c0ecb8bf28eb 14868 }
Marko Mikulicic 0:c0ecb8bf28eb 14869 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14870 break;
Marko Mikulicic 0:c0ecb8bf28eb 14871 }
Marko Mikulicic 0:c0ecb8bf28eb 14872 case OP_NE_NE: {
Marko Mikulicic 0:c0ecb8bf28eb 14873 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14874 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14875 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14876 res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) != 0);
Marko Mikulicic 0:c0ecb8bf28eb 14877 } else if (v1 == v2 && v1 == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 14878 res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14879 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14880 res = v7_mk_boolean(v7, v1 != v2);
Marko Mikulicic 0:c0ecb8bf28eb 14881 }
Marko Mikulicic 0:c0ecb8bf28eb 14882 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14883 break;
Marko Mikulicic 0:c0ecb8bf28eb 14884 }
Marko Mikulicic 0:c0ecb8bf28eb 14885 case OP_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 14886 case OP_NE: {
Marko Mikulicic 0:c0ecb8bf28eb 14887 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14888 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14889 /*
Marko Mikulicic 0:c0ecb8bf28eb 14890 * TODO(dfrank) : it's not really correct. Fix it accordingly to
Marko Mikulicic 0:c0ecb8bf28eb 14891 * the p. 4.9 of The Definitive Guide (page 71)
Marko Mikulicic 0:c0ecb8bf28eb 14892 */
Marko Mikulicic 0:c0ecb8bf28eb 14893 if (((v7_is_object(v1) || v7_is_object(v2)) && v1 == v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14894 res = v7_mk_boolean(v7, op == OP_EQ);
Marko Mikulicic 0:c0ecb8bf28eb 14895 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14896 break;
Marko Mikulicic 0:c0ecb8bf28eb 14897 } else if (v7_is_undefined(v1) || v7_is_null(v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 14898 res = v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 14899 v7, (op != OP_EQ) ^ (v7_is_undefined(v2) || v7_is_null(v2)));
Marko Mikulicic 0:c0ecb8bf28eb 14900 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14901 break;
Marko Mikulicic 0:c0ecb8bf28eb 14902 } else if (v7_is_undefined(v2) || v7_is_null(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14903 res = v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 14904 v7, (op != OP_EQ) ^ (v7_is_undefined(v1) || v7_is_null(v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14905 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14906 break;
Marko Mikulicic 0:c0ecb8bf28eb 14907 }
Marko Mikulicic 0:c0ecb8bf28eb 14908
Marko Mikulicic 0:c0ecb8bf28eb 14909 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14910 int cmp = s_cmp(v7, v1, v2);
Marko Mikulicic 0:c0ecb8bf28eb 14911 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14912 case OP_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 14913 res = v7_mk_boolean(v7, cmp == 0);
Marko Mikulicic 0:c0ecb8bf28eb 14914 break;
Marko Mikulicic 0:c0ecb8bf28eb 14915 case OP_NE:
Marko Mikulicic 0:c0ecb8bf28eb 14916 res = v7_mk_boolean(v7, cmp != 0);
Marko Mikulicic 0:c0ecb8bf28eb 14917 break;
Marko Mikulicic 0:c0ecb8bf28eb 14918 default:
Marko Mikulicic 0:c0ecb8bf28eb 14919 /* should never be here */
Marko Mikulicic 0:c0ecb8bf28eb 14920 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14921 }
Marko Mikulicic 0:c0ecb8bf28eb 14922 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14923 /* Convert both operands to numbers */
Marko Mikulicic 0:c0ecb8bf28eb 14924
Marko Mikulicic 0:c0ecb8bf28eb 14925 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14926 BTRY(to_number_v(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14927
Marko Mikulicic 0:c0ecb8bf28eb 14928 res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14929 v7_get_double(v7, v2)));
Marko Mikulicic 0:c0ecb8bf28eb 14930 }
Marko Mikulicic 0:c0ecb8bf28eb 14931 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14932 break;
Marko Mikulicic 0:c0ecb8bf28eb 14933 }
Marko Mikulicic 0:c0ecb8bf28eb 14934 case OP_LT:
Marko Mikulicic 0:c0ecb8bf28eb 14935 case OP_LE:
Marko Mikulicic 0:c0ecb8bf28eb 14936 case OP_GT:
Marko Mikulicic 0:c0ecb8bf28eb 14937 case OP_GE: {
Marko Mikulicic 0:c0ecb8bf28eb 14938 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14939 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14940 BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_NUMBER, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14941 BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_NUMBER, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14942
Marko Mikulicic 0:c0ecb8bf28eb 14943 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14944 int cmp = s_cmp(v7, v1, v2);
Marko Mikulicic 0:c0ecb8bf28eb 14945 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14946 case OP_LT:
Marko Mikulicic 0:c0ecb8bf28eb 14947 res = v7_mk_boolean(v7, cmp < 0);
Marko Mikulicic 0:c0ecb8bf28eb 14948 break;
Marko Mikulicic 0:c0ecb8bf28eb 14949 case OP_LE:
Marko Mikulicic 0:c0ecb8bf28eb 14950 res = v7_mk_boolean(v7, cmp <= 0);
Marko Mikulicic 0:c0ecb8bf28eb 14951 break;
Marko Mikulicic 0:c0ecb8bf28eb 14952 case OP_GT:
Marko Mikulicic 0:c0ecb8bf28eb 14953 res = v7_mk_boolean(v7, cmp > 0);
Marko Mikulicic 0:c0ecb8bf28eb 14954 break;
Marko Mikulicic 0:c0ecb8bf28eb 14955 case OP_GE:
Marko Mikulicic 0:c0ecb8bf28eb 14956 res = v7_mk_boolean(v7, cmp >= 0);
Marko Mikulicic 0:c0ecb8bf28eb 14957 break;
Marko Mikulicic 0:c0ecb8bf28eb 14958 default:
Marko Mikulicic 0:c0ecb8bf28eb 14959 /* should never be here */
Marko Mikulicic 0:c0ecb8bf28eb 14960 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14961 }
Marko Mikulicic 0:c0ecb8bf28eb 14962 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14963 /* Convert both operands to numbers */
Marko Mikulicic 0:c0ecb8bf28eb 14964
Marko Mikulicic 0:c0ecb8bf28eb 14965 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14966 BTRY(to_number_v(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14967
Marko Mikulicic 0:c0ecb8bf28eb 14968 res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14969 v7_get_double(v7, v2)));
Marko Mikulicic 0:c0ecb8bf28eb 14970 }
Marko Mikulicic 0:c0ecb8bf28eb 14971 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14972 break;
Marko Mikulicic 0:c0ecb8bf28eb 14973 }
Marko Mikulicic 0:c0ecb8bf28eb 14974 case OP_INSTANCEOF: {
Marko Mikulicic 0:c0ecb8bf28eb 14975 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14976 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14977 if (!v7_is_callable(v7, v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14978 BTRY(v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 14979 "Expecting a function in instanceof check"));
Marko Mikulicic 0:c0ecb8bf28eb 14980 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 14981 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14982 PUSH(v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 14983 v7, is_prototype_of(v7, v1, v7_get(v7, v2, "prototype", 9))));
Marko Mikulicic 0:c0ecb8bf28eb 14984 }
Marko Mikulicic 0:c0ecb8bf28eb 14985 break;
Marko Mikulicic 0:c0ecb8bf28eb 14986 }
Marko Mikulicic 0:c0ecb8bf28eb 14987 case OP_TYPEOF:
Marko Mikulicic 0:c0ecb8bf28eb 14988 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14989 switch (val_type(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 14990 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 14991 res = v7_mk_string(v7, "number", 6, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14992 break;
Marko Mikulicic 0:c0ecb8bf28eb 14993 case V7_TYPE_STRING:
Marko Mikulicic 0:c0ecb8bf28eb 14994 res = v7_mk_string(v7, "string", 6, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14995 break;
Marko Mikulicic 0:c0ecb8bf28eb 14996 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 14997 res = v7_mk_string(v7, "boolean", 7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14998 break;
Marko Mikulicic 0:c0ecb8bf28eb 14999 case V7_TYPE_FUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 15000 case V7_TYPE_CFUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 15001 case V7_TYPE_CFUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 15002 res = v7_mk_string(v7, "function", 8, 1);
Marko Mikulicic 0:c0ecb8bf28eb 15003 break;
Marko Mikulicic 0:c0ecb8bf28eb 15004 case V7_TYPE_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 15005 res = v7_mk_string(v7, "undefined", 9, 1);
Marko Mikulicic 0:c0ecb8bf28eb 15006 break;
Marko Mikulicic 0:c0ecb8bf28eb 15007 default:
Marko Mikulicic 0:c0ecb8bf28eb 15008 res = v7_mk_string(v7, "object", 6, 1);
Marko Mikulicic 0:c0ecb8bf28eb 15009 break;
Marko Mikulicic 0:c0ecb8bf28eb 15010 }
Marko Mikulicic 0:c0ecb8bf28eb 15011 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 15012 break;
Marko Mikulicic 0:c0ecb8bf28eb 15013 case OP_IN: {
Marko Mikulicic 0:c0ecb8bf28eb 15014 struct v7_property *prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15015 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15016 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15017 BTRY(to_string(v7, v1, NULL, buf, sizeof(buf), NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15018 prop = v7_get_property(v7, v2, buf, ~0);
Marko Mikulicic 0:c0ecb8bf28eb 15019 PUSH(v7_mk_boolean(v7, prop != NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15020 } break;
Marko Mikulicic 0:c0ecb8bf28eb 15021 case OP_GET:
Marko Mikulicic 0:c0ecb8bf28eb 15022 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15023 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15024 BTRY(v7_get_throwing_v(v7, v1, v2, &v3));
Marko Mikulicic 0:c0ecb8bf28eb 15025 PUSH(v3);
Marko Mikulicic 0:c0ecb8bf28eb 15026 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 15027 v7->vals.last_name[1] = v7->vals.last_name[0];
Marko Mikulicic 0:c0ecb8bf28eb 15028 v7->vals.last_name[0] = v2;
Marko Mikulicic 0:c0ecb8bf28eb 15029 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15030 break;
Marko Mikulicic 0:c0ecb8bf28eb 15031 case OP_SET: {
Marko Mikulicic 0:c0ecb8bf28eb 15032 v3 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15033 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15034 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15035
Marko Mikulicic 0:c0ecb8bf28eb 15036 /* convert name to string, if it's not already */
Marko Mikulicic 0:c0ecb8bf28eb 15037 BTRY(to_string(v7, v2, &v2, NULL, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15038
Marko Mikulicic 0:c0ecb8bf28eb 15039 /* set value */
Marko Mikulicic 0:c0ecb8bf28eb 15040 BTRY(set_property_v(v7, v1, v2, v3, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15041
Marko Mikulicic 0:c0ecb8bf28eb 15042 PUSH(v3);
Marko Mikulicic 0:c0ecb8bf28eb 15043 break;
Marko Mikulicic 0:c0ecb8bf28eb 15044 }
Marko Mikulicic 0:c0ecb8bf28eb 15045 case OP_GET_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 15046 case OP_SAFE_GET_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 15047 struct v7_property *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15048 assert(r.ops < r.end - 1);
Marko Mikulicic 0:c0ecb8bf28eb 15049 v1 = bcode_decode_lit(v7, r.bcode, &r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15050 BTRY(v7_get_property_v(v7, get_scope(v7), v1, &p));
Marko Mikulicic 0:c0ecb8bf28eb 15051 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15052 if (op == OP_SAFE_GET_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 15053 PUSH(V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 15054 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15055 /* variable does not exist: Reference Error */
Marko Mikulicic 0:c0ecb8bf28eb 15056 V7_TRY(bcode_throw_reference_error(v7, &r, v1));
Marko Mikulicic 0:c0ecb8bf28eb 15057 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15058 }
Marko Mikulicic 0:c0ecb8bf28eb 15059 break;
Marko Mikulicic 0:c0ecb8bf28eb 15060 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15061 BTRY(v7_property_value(v7, get_scope(v7), p, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 15062 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 15063 }
Marko Mikulicic 0:c0ecb8bf28eb 15064 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 15065 v7->vals.last_name[0] = v1;
Marko Mikulicic 0:c0ecb8bf28eb 15066 v7->vals.last_name[1] = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15067 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15068 break;
Marko Mikulicic 0:c0ecb8bf28eb 15069 }
Marko Mikulicic 0:c0ecb8bf28eb 15070 case OP_SET_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 15071 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 15072 v3 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15073 v2 = bcode_decode_lit(v7, r.bcode, &r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15074 v1 = get_scope(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15075
Marko Mikulicic 0:c0ecb8bf28eb 15076 BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15077 prop = v7_get_property(v7, v1, buf, strlen(buf));
Marko Mikulicic 0:c0ecb8bf28eb 15078 if (prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15079 /* Property already exists: update its value */
Marko Mikulicic 0:c0ecb8bf28eb 15080 /*
Marko Mikulicic 0:c0ecb8bf28eb 15081 * TODO(dfrank): currently we can't use `def_property_v()` here,
Marko Mikulicic 0:c0ecb8bf28eb 15082 * because if the property was already found somewhere in the
Marko Mikulicic 0:c0ecb8bf28eb 15083 * prototype chain, then it should be updated, instead of creating a
Marko Mikulicic 0:c0ecb8bf28eb 15084 * new one on the top of the scope.
Marko Mikulicic 0:c0ecb8bf28eb 15085 *
Marko Mikulicic 0:c0ecb8bf28eb 15086 * Probably we need to make `def_property_v()` more generic and
Marko Mikulicic 0:c0ecb8bf28eb 15087 * use it here; or split `def_property_v()` into smaller pieces and
Marko Mikulicic 0:c0ecb8bf28eb 15088 * use one of them here.
Marko Mikulicic 0:c0ecb8bf28eb 15089 */
Marko Mikulicic 0:c0ecb8bf28eb 15090 if (!(prop->attributes & V7_PROPERTY_NON_WRITABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 15091 prop->value = v3;
Marko Mikulicic 0:c0ecb8bf28eb 15092 }
Marko Mikulicic 0:c0ecb8bf28eb 15093 } else if (!r.bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 15094 /*
Marko Mikulicic 0:c0ecb8bf28eb 15095 * Property does not exist: since we're not in strict mode, let's
Marko Mikulicic 0:c0ecb8bf28eb 15096 * create new property at Global Object
Marko Mikulicic 0:c0ecb8bf28eb 15097 */
Marko Mikulicic 0:c0ecb8bf28eb 15098 BTRY(set_property_v(v7, v7_get_global(v7), v2, v3, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15099 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15100 /*
Marko Mikulicic 0:c0ecb8bf28eb 15101 * In strict mode, throw reference error instead of polluting Global
Marko Mikulicic 0:c0ecb8bf28eb 15102 * Object
Marko Mikulicic 0:c0ecb8bf28eb 15103 */
Marko Mikulicic 0:c0ecb8bf28eb 15104 V7_TRY(bcode_throw_reference_error(v7, &r, v2));
Marko Mikulicic 0:c0ecb8bf28eb 15105 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15106 }
Marko Mikulicic 0:c0ecb8bf28eb 15107 PUSH(v3);
Marko Mikulicic 0:c0ecb8bf28eb 15108 break;
Marko Mikulicic 0:c0ecb8bf28eb 15109 }
Marko Mikulicic 0:c0ecb8bf28eb 15110 case OP_JMP: {
Marko Mikulicic 0:c0ecb8bf28eb 15111 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15112 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15113 break;
Marko Mikulicic 0:c0ecb8bf28eb 15114 }
Marko Mikulicic 0:c0ecb8bf28eb 15115 case OP_JMP_FALSE: {
Marko Mikulicic 0:c0ecb8bf28eb 15116 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15117 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15118 if (!v7_is_truthy(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15119 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15120 }
Marko Mikulicic 0:c0ecb8bf28eb 15121 break;
Marko Mikulicic 0:c0ecb8bf28eb 15122 }
Marko Mikulicic 0:c0ecb8bf28eb 15123 case OP_JMP_TRUE: {
Marko Mikulicic 0:c0ecb8bf28eb 15124 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15125 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15126 if (v7_is_truthy(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15127 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15128 }
Marko Mikulicic 0:c0ecb8bf28eb 15129 break;
Marko Mikulicic 0:c0ecb8bf28eb 15130 }
Marko Mikulicic 0:c0ecb8bf28eb 15131 case OP_JMP_TRUE_DROP: {
Marko Mikulicic 0:c0ecb8bf28eb 15132 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15133 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15134 if (v7_is_truthy(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15135 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15136 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15137 POP();
Marko Mikulicic 0:c0ecb8bf28eb 15138 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15139 }
Marko Mikulicic 0:c0ecb8bf28eb 15140 break;
Marko Mikulicic 0:c0ecb8bf28eb 15141 }
Marko Mikulicic 0:c0ecb8bf28eb 15142 case OP_JMP_IF_CONTINUE: {
Marko Mikulicic 0:c0ecb8bf28eb 15143 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15144 if (v7->is_continuing) {
Marko Mikulicic 0:c0ecb8bf28eb 15145 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15146 }
Marko Mikulicic 0:c0ecb8bf28eb 15147 v7->is_continuing = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15148 break;
Marko Mikulicic 0:c0ecb8bf28eb 15149 }
Marko Mikulicic 0:c0ecb8bf28eb 15150 case OP_CREATE_OBJ:
Marko Mikulicic 0:c0ecb8bf28eb 15151 PUSH(v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 15152 break;
Marko Mikulicic 0:c0ecb8bf28eb 15153 case OP_CREATE_ARR:
Marko Mikulicic 0:c0ecb8bf28eb 15154 PUSH(v7_mk_array(v7));
Marko Mikulicic 0:c0ecb8bf28eb 15155 break;
Marko Mikulicic 0:c0ecb8bf28eb 15156 case OP_PUSH_PROP_ITER_CTX: {
Marko Mikulicic 0:c0ecb8bf28eb 15157 struct prop_iter_ctx *ctx =
Marko Mikulicic 0:c0ecb8bf28eb 15158 (struct prop_iter_ctx *) calloc(1, sizeof(*ctx));
Marko Mikulicic 0:c0ecb8bf28eb 15159 BTRY(init_prop_iter_ctx(v7, TOS(), 1, ctx));
Marko Mikulicic 0:c0ecb8bf28eb 15160 v1 = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15161 v7_set_user_data(v7, v1, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15162 v7_set_destructor_cb(v7, v1, prop_iter_ctx_dtor);
Marko Mikulicic 0:c0ecb8bf28eb 15163 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15164 break;
Marko Mikulicic 0:c0ecb8bf28eb 15165 }
Marko Mikulicic 0:c0ecb8bf28eb 15166 case OP_NEXT_PROP: {
Marko Mikulicic 0:c0ecb8bf28eb 15167 struct prop_iter_ctx *ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15168 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15169 v1 = POP(); /* ctx */
Marko Mikulicic 0:c0ecb8bf28eb 15170 v2 = POP(); /* object */
Marko Mikulicic 0:c0ecb8bf28eb 15171
Marko Mikulicic 0:c0ecb8bf28eb 15172 ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1);
Marko Mikulicic 0:c0ecb8bf28eb 15173
Marko Mikulicic 0:c0ecb8bf28eb 15174 if (v7_is_object(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 15175 v7_prop_attr_t attrs;
Marko Mikulicic 0:c0ecb8bf28eb 15176
Marko Mikulicic 0:c0ecb8bf28eb 15177 do {
Marko Mikulicic 0:c0ecb8bf28eb 15178 /* iterate properties until we find a non-hidden enumerable one */
Marko Mikulicic 0:c0ecb8bf28eb 15179 do {
Marko Mikulicic 0:c0ecb8bf28eb 15180 BTRY(next_prop(v7, ctx, &res, NULL, &attrs, &ok));
Marko Mikulicic 0:c0ecb8bf28eb 15181 } while (ok && (attrs & (_V7_PROPERTY_HIDDEN |
Marko Mikulicic 0:c0ecb8bf28eb 15182 V7_PROPERTY_NON_ENUMERABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 15183
Marko Mikulicic 0:c0ecb8bf28eb 15184 if (!ok) {
Marko Mikulicic 0:c0ecb8bf28eb 15185 /* no more properties in this object: proceed to the prototype */
Marko Mikulicic 0:c0ecb8bf28eb 15186 v2 = v7_get_proto(v7, v2);
Marko Mikulicic 0:c0ecb8bf28eb 15187 if (get_generic_object_struct(v2) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15188 /*
Marko Mikulicic 0:c0ecb8bf28eb 15189 * the prototype is a generic object, so, init the context for
Marko Mikulicic 0:c0ecb8bf28eb 15190 * props iteration
Marko Mikulicic 0:c0ecb8bf28eb 15191 */
Marko Mikulicic 0:c0ecb8bf28eb 15192 v7_destruct_prop_iter_ctx(v7, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15193 BTRY(init_prop_iter_ctx(v7, v2, 1, ctx));
Marko Mikulicic 0:c0ecb8bf28eb 15194 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15195 /*
Marko Mikulicic 0:c0ecb8bf28eb 15196 * we can't iterate the prototype's props, so, just stop
Marko Mikulicic 0:c0ecb8bf28eb 15197 * iteration.
Marko Mikulicic 0:c0ecb8bf28eb 15198 */
Marko Mikulicic 0:c0ecb8bf28eb 15199 ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15200 }
Marko Mikulicic 0:c0ecb8bf28eb 15201 }
Marko Mikulicic 0:c0ecb8bf28eb 15202 } while (!ok && ctx != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15203 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15204 /*
Marko Mikulicic 0:c0ecb8bf28eb 15205 * Not an object: reset the context.
Marko Mikulicic 0:c0ecb8bf28eb 15206 */
Marko Mikulicic 0:c0ecb8bf28eb 15207 ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15208 }
Marko Mikulicic 0:c0ecb8bf28eb 15209
Marko Mikulicic 0:c0ecb8bf28eb 15210 if (ctx == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15211 PUSH(v7_mk_boolean(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 15212
Marko Mikulicic 0:c0ecb8bf28eb 15213 /*
Marko Mikulicic 0:c0ecb8bf28eb 15214 * We could leave the context unfreed, and let the
Marko Mikulicic 0:c0ecb8bf28eb 15215 * `prop_iter_ctx_dtor()` free it when the v1 will be GC-d, but
Marko Mikulicic 0:c0ecb8bf28eb 15216 * let's do that earlier.
Marko Mikulicic 0:c0ecb8bf28eb 15217 */
Marko Mikulicic 0:c0ecb8bf28eb 15218 ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1);
Marko Mikulicic 0:c0ecb8bf28eb 15219 v7_destruct_prop_iter_ctx(v7, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15220 free(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15221 v7_set_user_data(v7, v1, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15222 v7_set_destructor_cb(v7, v1, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15223 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15224 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 15225 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15226 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 15227 PUSH(v7_mk_boolean(v7, 1));
Marko Mikulicic 0:c0ecb8bf28eb 15228 }
Marko Mikulicic 0:c0ecb8bf28eb 15229 break;
Marko Mikulicic 0:c0ecb8bf28eb 15230 }
Marko Mikulicic 0:c0ecb8bf28eb 15231 case OP_FUNC_LIT: {
Marko Mikulicic 0:c0ecb8bf28eb 15232 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15233 v2 = bcode_instantiate_function(v7, v1);
Marko Mikulicic 0:c0ecb8bf28eb 15234 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 15235 break;
Marko Mikulicic 0:c0ecb8bf28eb 15236 }
Marko Mikulicic 0:c0ecb8bf28eb 15237 case OP_CHECK_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 15238 v1 = TOS();
Marko Mikulicic 0:c0ecb8bf28eb 15239 if (!v7_is_callable(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15240 int arity = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15241 enum v7_err ignore;
Marko Mikulicic 0:c0ecb8bf28eb 15242 /* tried to call non-function object: throw a TypeError */
Marko Mikulicic 0:c0ecb8bf28eb 15243
Marko Mikulicic 0:c0ecb8bf28eb 15244 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 15245 /*
Marko Mikulicic 0:c0ecb8bf28eb 15246 * try to provide some useful context for the error message
Marko Mikulicic 0:c0ecb8bf28eb 15247 * using a good-enough heuristics
Marko Mikulicic 0:c0ecb8bf28eb 15248 * but defer actual throw when process the incriminated call
Marko Mikulicic 0:c0ecb8bf28eb 15249 * in order to evaluate the arguments as required by the spec.
Marko Mikulicic 0:c0ecb8bf28eb 15250 */
Marko Mikulicic 0:c0ecb8bf28eb 15251 if (v7->last_ops[0] == OP_GET_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 15252 arity = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15253 } else if (v7->last_ops[0] == OP_GET &&
Marko Mikulicic 0:c0ecb8bf28eb 15254 v7->last_ops[1] == OP_PUSH_LIT) {
Marko Mikulicic 0:c0ecb8bf28eb 15255 /*
Marko Mikulicic 0:c0ecb8bf28eb 15256 * OP_PUSH_LIT is used to both push property names for OP_GET
Marko Mikulicic 0:c0ecb8bf28eb 15257 * and for pushing actual literals. During PUSH_LIT push lit
Marko Mikulicic 0:c0ecb8bf28eb 15258 * evaluation we reset the last name variable in case the literal
Marko Mikulicic 0:c0ecb8bf28eb 15259 * is not a string, such as in `[].foo()`.
Marko Mikulicic 0:c0ecb8bf28eb 15260 * Unfortunately it doesn't handle `"foo".bar()`; could be
Marko Mikulicic 0:c0ecb8bf28eb 15261 * solved by adding another bytecode for property literals but
Marko Mikulicic 0:c0ecb8bf28eb 15262 * probably it doesn't matter much.
Marko Mikulicic 0:c0ecb8bf28eb 15263 */
Marko Mikulicic 0:c0ecb8bf28eb 15264 if (v7_is_undefined(v7->vals.last_name[1])) {
Marko Mikulicic 0:c0ecb8bf28eb 15265 arity = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15266 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15267 arity = 2;
Marko Mikulicic 0:c0ecb8bf28eb 15268 }
Marko Mikulicic 0:c0ecb8bf28eb 15269 }
Marko Mikulicic 0:c0ecb8bf28eb 15270 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15271
Marko Mikulicic 0:c0ecb8bf28eb 15272 switch (arity) {
Marko Mikulicic 0:c0ecb8bf28eb 15273 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 15274 ignore = v7_throwf(v7, TYPE_ERROR, "value is not a function");
Marko Mikulicic 0:c0ecb8bf28eb 15275 break;
Marko Mikulicic 0:c0ecb8bf28eb 15276 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 15277
Marko Mikulicic 0:c0ecb8bf28eb 15278 case 1:
Marko Mikulicic 0:c0ecb8bf28eb 15279 ignore = v7_throwf(v7, TYPE_ERROR, "%s is not a function",
Marko Mikulicic 0:c0ecb8bf28eb 15280 v7_get_cstring(v7, &v7->vals.last_name[0]));
Marko Mikulicic 0:c0ecb8bf28eb 15281 break;
Marko Mikulicic 0:c0ecb8bf28eb 15282 case 2:
Marko Mikulicic 0:c0ecb8bf28eb 15283 ignore = v7_throwf(v7, TYPE_ERROR, "%s.%s is not a function",
Marko Mikulicic 0:c0ecb8bf28eb 15284 v7_get_cstring(v7, &v7->vals.last_name[1]),
Marko Mikulicic 0:c0ecb8bf28eb 15285 v7_get_cstring(v7, &v7->vals.last_name[0]));
Marko Mikulicic 0:c0ecb8bf28eb 15286 break;
Marko Mikulicic 0:c0ecb8bf28eb 15287 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15288 };
Marko Mikulicic 0:c0ecb8bf28eb 15289
Marko Mikulicic 0:c0ecb8bf28eb 15290 v7->vals.call_check_ex = v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 15291 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15292 (void) ignore;
Marko Mikulicic 0:c0ecb8bf28eb 15293 }
Marko Mikulicic 0:c0ecb8bf28eb 15294 break;
Marko Mikulicic 0:c0ecb8bf28eb 15295 case OP_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 15296 case OP_NEW: {
Marko Mikulicic 0:c0ecb8bf28eb 15297 /* Naive implementation pending stack frame redesign */
Marko Mikulicic 0:c0ecb8bf28eb 15298 int args = (int) *(++r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15299 uint8_t is_constructor = (op == OP_NEW);
Marko Mikulicic 0:c0ecb8bf28eb 15300
Marko Mikulicic 0:c0ecb8bf28eb 15301 if (SP() < (args + 1 /*func*/ + 1 /*this*/)) {
Marko Mikulicic 0:c0ecb8bf28eb 15302 BTRY(v7_throwf(v7, INTERNAL_ERROR, "stack underflow"));
Marko Mikulicic 0:c0ecb8bf28eb 15303 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15304 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15305 v2 = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15306 while (args > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15307 BTRY(v7_array_set_throwing(v7, v2, --args, POP(), NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15308 }
Marko Mikulicic 0:c0ecb8bf28eb 15309 /* pop function to call */
Marko Mikulicic 0:c0ecb8bf28eb 15310 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15311
Marko Mikulicic 0:c0ecb8bf28eb 15312 /* pop `this` */
Marko Mikulicic 0:c0ecb8bf28eb 15313 v3 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15314
Marko Mikulicic 0:c0ecb8bf28eb 15315 /*
Marko Mikulicic 0:c0ecb8bf28eb 15316 * adjust `this` if the function is called with the constructor
Marko Mikulicic 0:c0ecb8bf28eb 15317 * invocation pattern
Marko Mikulicic 0:c0ecb8bf28eb 15318 */
Marko Mikulicic 0:c0ecb8bf28eb 15319 if (is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 15320 /*
Marko Mikulicic 0:c0ecb8bf28eb 15321 * The function is invoked as a constructor: we ignore `this`
Marko Mikulicic 0:c0ecb8bf28eb 15322 * value popped from stack, create new object and set prototype.
Marko Mikulicic 0:c0ecb8bf28eb 15323 */
Marko Mikulicic 0:c0ecb8bf28eb 15324
Marko Mikulicic 0:c0ecb8bf28eb 15325 /*
Marko Mikulicic 0:c0ecb8bf28eb 15326 * get "prototype" property from the constructor function,
Marko Mikulicic 0:c0ecb8bf28eb 15327 * and make sure it's an object
Marko Mikulicic 0:c0ecb8bf28eb 15328 */
Marko Mikulicic 0:c0ecb8bf28eb 15329 v4 = v7_get(v7, v1 /*func*/, "prototype", 9);
Marko Mikulicic 0:c0ecb8bf28eb 15330 if (!v7_is_object(v4)) {
Marko Mikulicic 0:c0ecb8bf28eb 15331 /* TODO(dfrank): box primitive value */
Marko Mikulicic 0:c0ecb8bf28eb 15332 BTRY(v7_throwf(
Marko Mikulicic 0:c0ecb8bf28eb 15333 v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 15334 "Cannot set a primitive value as object prototype"));
Marko Mikulicic 0:c0ecb8bf28eb 15335 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15336 } else if (is_cfunction_lite(v4)) {
Marko Mikulicic 0:c0ecb8bf28eb 15337 /*
Marko Mikulicic 0:c0ecb8bf28eb 15338 * TODO(dfrank): maybe add support for a cfunction pointer to be
Marko Mikulicic 0:c0ecb8bf28eb 15339 * a prototype
Marko Mikulicic 0:c0ecb8bf28eb 15340 */
Marko Mikulicic 0:c0ecb8bf28eb 15341 BTRY(v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 15342 "Not implemented: cfunction as a prototype"));
Marko Mikulicic 0:c0ecb8bf28eb 15343 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15344 }
Marko Mikulicic 0:c0ecb8bf28eb 15345
Marko Mikulicic 0:c0ecb8bf28eb 15346 /* create an object with given prototype */
Marko Mikulicic 0:c0ecb8bf28eb 15347 v3 = mk_object(v7, v4 /*prototype*/);
Marko Mikulicic 0:c0ecb8bf28eb 15348 v4 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15349 }
Marko Mikulicic 0:c0ecb8bf28eb 15350
Marko Mikulicic 0:c0ecb8bf28eb 15351 if (!v7_is_callable(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15352 /* tried to call non-function object: throw a TypeError */
Marko Mikulicic 0:c0ecb8bf28eb 15353 BTRY(v7_throw(v7, v7->vals.call_check_ex));
Marko Mikulicic 0:c0ecb8bf28eb 15354 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15355 } else if (is_cfunction_lite(v1) || is_cfunction_obj(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15356 /* call cfunction */
Marko Mikulicic 0:c0ecb8bf28eb 15357
Marko Mikulicic 0:c0ecb8bf28eb 15358 /*
Marko Mikulicic 0:c0ecb8bf28eb 15359 * In "function invocation pattern", the `this` value popped from
Marko Mikulicic 0:c0ecb8bf28eb 15360 * stack is an `undefined`. And in non-strict mode, we should change
Marko Mikulicic 0:c0ecb8bf28eb 15361 * it to global object.
Marko Mikulicic 0:c0ecb8bf28eb 15362 */
Marko Mikulicic 0:c0ecb8bf28eb 15363 if (!is_constructor && !r.bcode->strict_mode &&
Marko Mikulicic 0:c0ecb8bf28eb 15364 v7_is_undefined(v3)) {
Marko Mikulicic 0:c0ecb8bf28eb 15365 v3 = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 15366 }
Marko Mikulicic 0:c0ecb8bf28eb 15367
Marko Mikulicic 0:c0ecb8bf28eb 15368 BTRY(call_cfunction(v7, v1 /*func*/, v3 /*this*/, v2 /*args*/,
Marko Mikulicic 0:c0ecb8bf28eb 15369 is_constructor, &v4));
Marko Mikulicic 0:c0ecb8bf28eb 15370
Marko Mikulicic 0:c0ecb8bf28eb 15371 /* push value returned from C function to bcode stack */
Marko Mikulicic 0:c0ecb8bf28eb 15372 PUSH(v4);
Marko Mikulicic 0:c0ecb8bf28eb 15373
Marko Mikulicic 0:c0ecb8bf28eb 15374 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15375 char *ops;
Marko Mikulicic 0:c0ecb8bf28eb 15376 struct v7_js_function *func = get_js_function_struct(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15377
Marko Mikulicic 0:c0ecb8bf28eb 15378 /*
Marko Mikulicic 0:c0ecb8bf28eb 15379 * In "function invocation pattern", the `this` value popped from
Marko Mikulicic 0:c0ecb8bf28eb 15380 * stack is an `undefined`. And in non-strict mode, we should change
Marko Mikulicic 0:c0ecb8bf28eb 15381 * it to global object.
Marko Mikulicic 0:c0ecb8bf28eb 15382 */
Marko Mikulicic 0:c0ecb8bf28eb 15383 if (!is_constructor && !func->bcode->strict_mode &&
Marko Mikulicic 0:c0ecb8bf28eb 15384 v7_is_undefined(v3)) {
Marko Mikulicic 0:c0ecb8bf28eb 15385 v3 = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 15386 }
Marko Mikulicic 0:c0ecb8bf28eb 15387
Marko Mikulicic 0:c0ecb8bf28eb 15388 scope_frame = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15389
Marko Mikulicic 0:c0ecb8bf28eb 15390 /*
Marko Mikulicic 0:c0ecb8bf28eb 15391 * Before actual opcodes, `ops` contains one or more
Marko Mikulicic 0:c0ecb8bf28eb 15392 * null-terminated strings: first of all, the function name (if the
Marko Mikulicic 0:c0ecb8bf28eb 15393 * function is anonymous, it's an empty string).
Marko Mikulicic 0:c0ecb8bf28eb 15394 *
Marko Mikulicic 0:c0ecb8bf28eb 15395 * Then, argument names follow. We know number of arguments, so, we
Marko Mikulicic 0:c0ecb8bf28eb 15396 * know how many names to take.
Marko Mikulicic 0:c0ecb8bf28eb 15397 *
Marko Mikulicic 0:c0ecb8bf28eb 15398 * And then, local variable names follow. We know total number of
Marko Mikulicic 0:c0ecb8bf28eb 15399 * strings (`names_cnt`), so, again, we know how many names to
Marko Mikulicic 0:c0ecb8bf28eb 15400 * take.
Marko Mikulicic 0:c0ecb8bf28eb 15401 */
Marko Mikulicic 0:c0ecb8bf28eb 15402
Marko Mikulicic 0:c0ecb8bf28eb 15403 ops = func->bcode->ops.p;
Marko Mikulicic 0:c0ecb8bf28eb 15404
Marko Mikulicic 0:c0ecb8bf28eb 15405 /* populate function itself */
Marko Mikulicic 0:c0ecb8bf28eb 15406 ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 15407 BTRY(def_property_v(v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 15408 v1, 0 /*not assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15409
Marko Mikulicic 0:c0ecb8bf28eb 15410 /* populate arguments */
Marko Mikulicic 0:c0ecb8bf28eb 15411 {
Marko Mikulicic 0:c0ecb8bf28eb 15412 int arg_num;
Marko Mikulicic 0:c0ecb8bf28eb 15413 for (arg_num = 0; arg_num < func->bcode->args_cnt; ++arg_num) {
Marko Mikulicic 0:c0ecb8bf28eb 15414 ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 15415 BTRY(def_property_v(
Marko Mikulicic 0:c0ecb8bf28eb 15416 v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 15417 v7_array_get(v7, v2, arg_num), 0 /*not assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15418 }
Marko Mikulicic 0:c0ecb8bf28eb 15419 }
Marko Mikulicic 0:c0ecb8bf28eb 15420
Marko Mikulicic 0:c0ecb8bf28eb 15421 /* populate `arguments` object */
Marko Mikulicic 0:c0ecb8bf28eb 15422
Marko Mikulicic 0:c0ecb8bf28eb 15423 /*
Marko Mikulicic 0:c0ecb8bf28eb 15424 * TODO(dfrank): it's actually much more complicated than that:
Marko Mikulicic 0:c0ecb8bf28eb 15425 * it's not an array, it's an array-like object. More, in
Marko Mikulicic 0:c0ecb8bf28eb 15426 * non-strict mode, elements of `arguments` object are just aliases
Marko Mikulicic 0:c0ecb8bf28eb 15427 * for actual arguments, so this one:
Marko Mikulicic 0:c0ecb8bf28eb 15428 *
Marko Mikulicic 0:c0ecb8bf28eb 15429 * `(function(a){arguments[0]=2; return a;})(1);`
Marko Mikulicic 0:c0ecb8bf28eb 15430 *
Marko Mikulicic 0:c0ecb8bf28eb 15431 * should yield 2. Currently, it yields 1.
Marko Mikulicic 0:c0ecb8bf28eb 15432 */
Marko Mikulicic 0:c0ecb8bf28eb 15433 v7_def(v7, scope_frame, "arguments", 9, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 15434 v2);
Marko Mikulicic 0:c0ecb8bf28eb 15435
Marko Mikulicic 0:c0ecb8bf28eb 15436 /* populate local variables */
Marko Mikulicic 0:c0ecb8bf28eb 15437 {
Marko Mikulicic 0:c0ecb8bf28eb 15438 uint8_t loc_num;
Marko Mikulicic 0:c0ecb8bf28eb 15439 uint8_t loc_cnt = func->bcode->names_cnt - func->bcode->args_cnt -
Marko Mikulicic 0:c0ecb8bf28eb 15440 1 /*func name*/;
Marko Mikulicic 0:c0ecb8bf28eb 15441 for (loc_num = 0; loc_num < loc_cnt; ++loc_num) {
Marko Mikulicic 0:c0ecb8bf28eb 15442 ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 15443 BTRY(def_property_v(v7, scope_frame, v4,
Marko Mikulicic 0:c0ecb8bf28eb 15444 V7_DESC_CONFIGURABLE(0), V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 15445 0 /*not assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15446 }
Marko Mikulicic 0:c0ecb8bf28eb 15447 }
Marko Mikulicic 0:c0ecb8bf28eb 15448
Marko Mikulicic 0:c0ecb8bf28eb 15449 /* transfer control to the function */
Marko Mikulicic 0:c0ecb8bf28eb 15450 V7_TRY(bcode_perform_call(v7, scope_frame, func, &r, v3 /*this*/,
Marko Mikulicic 0:c0ecb8bf28eb 15451 ops, is_constructor));
Marko Mikulicic 0:c0ecb8bf28eb 15452
Marko Mikulicic 0:c0ecb8bf28eb 15453 scope_frame = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15454 }
Marko Mikulicic 0:c0ecb8bf28eb 15455 }
Marko Mikulicic 0:c0ecb8bf28eb 15456 break;
Marko Mikulicic 0:c0ecb8bf28eb 15457 }
Marko Mikulicic 0:c0ecb8bf28eb 15458 case OP_RET:
Marko Mikulicic 0:c0ecb8bf28eb 15459 bcode_adjust_retval(v7, 1 /*explicit return*/);
Marko Mikulicic 0:c0ecb8bf28eb 15460 V7_TRY(bcode_perform_return(v7, &r, 1 /*take value from stack*/));
Marko Mikulicic 0:c0ecb8bf28eb 15461 break;
Marko Mikulicic 0:c0ecb8bf28eb 15462 case OP_DELETE:
Marko Mikulicic 0:c0ecb8bf28eb 15463 case OP_DELETE_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 15464 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 15465 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 15466
Marko Mikulicic 0:c0ecb8bf28eb 15467 res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 15468
Marko Mikulicic 0:c0ecb8bf28eb 15469 /* pop property name to delete */
Marko Mikulicic 0:c0ecb8bf28eb 15470 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15471
Marko Mikulicic 0:c0ecb8bf28eb 15472 if (op == OP_DELETE) {
Marko Mikulicic 0:c0ecb8bf28eb 15473 /* pop object to delete the property from */
Marko Mikulicic 0:c0ecb8bf28eb 15474 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15475 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15476 /* use scope as an object to delete the property from */
Marko Mikulicic 0:c0ecb8bf28eb 15477 v1 = get_scope(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15478 }
Marko Mikulicic 0:c0ecb8bf28eb 15479
Marko Mikulicic 0:c0ecb8bf28eb 15480 if (!v7_is_object(v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15481 /*
Marko Mikulicic 0:c0ecb8bf28eb 15482 * the "object" to delete a property from is not actually an object
Marko Mikulicic 0:c0ecb8bf28eb 15483 * (at least this can happen with cfunction pointers), will just
Marko Mikulicic 0:c0ecb8bf28eb 15484 * return `true`
Marko Mikulicic 0:c0ecb8bf28eb 15485 */
Marko Mikulicic 0:c0ecb8bf28eb 15486 goto delete_clean;
Marko Mikulicic 0:c0ecb8bf28eb 15487 }
Marko Mikulicic 0:c0ecb8bf28eb 15488
Marko Mikulicic 0:c0ecb8bf28eb 15489 BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), &name_len));
Marko Mikulicic 0:c0ecb8bf28eb 15490
Marko Mikulicic 0:c0ecb8bf28eb 15491 prop = v7_get_property(v7, v1, buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 15492 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15493 /* not found a property; will just return `true` */
Marko Mikulicic 0:c0ecb8bf28eb 15494 goto delete_clean;
Marko Mikulicic 0:c0ecb8bf28eb 15495 }
Marko Mikulicic 0:c0ecb8bf28eb 15496
Marko Mikulicic 0:c0ecb8bf28eb 15497 /* found needed property */
Marko Mikulicic 0:c0ecb8bf28eb 15498
Marko Mikulicic 0:c0ecb8bf28eb 15499 if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 15500 /*
Marko Mikulicic 0:c0ecb8bf28eb 15501 * this property is undeletable. In non-strict mode, we just
Marko Mikulicic 0:c0ecb8bf28eb 15502 * return `false`; otherwise, we throw.
Marko Mikulicic 0:c0ecb8bf28eb 15503 */
Marko Mikulicic 0:c0ecb8bf28eb 15504 if (!r.bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 15505 res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 15506 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15507 BTRY(v7_throwf(v7, TYPE_ERROR, "Cannot delete property '%s'", buf));
Marko Mikulicic 0:c0ecb8bf28eb 15508 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15509 }
Marko Mikulicic 0:c0ecb8bf28eb 15510 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15511 /*
Marko Mikulicic 0:c0ecb8bf28eb 15512 * delete property: when we operate on the current scope, we should
Marko Mikulicic 0:c0ecb8bf28eb 15513 * walk the prototype chain when deleting property.
Marko Mikulicic 0:c0ecb8bf28eb 15514 *
Marko Mikulicic 0:c0ecb8bf28eb 15515 * But when we operate on a "real" object, we should delete own
Marko Mikulicic 0:c0ecb8bf28eb 15516 * properties only.
Marko Mikulicic 0:c0ecb8bf28eb 15517 */
Marko Mikulicic 0:c0ecb8bf28eb 15518 if (op == OP_DELETE) {
Marko Mikulicic 0:c0ecb8bf28eb 15519 v7_del(v7, v1, buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 15520 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15521 del_property_deep(v7, v1, buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 15522 }
Marko Mikulicic 0:c0ecb8bf28eb 15523 }
Marko Mikulicic 0:c0ecb8bf28eb 15524
Marko Mikulicic 0:c0ecb8bf28eb 15525 delete_clean:
Marko Mikulicic 0:c0ecb8bf28eb 15526 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 15527 break;
Marko Mikulicic 0:c0ecb8bf28eb 15528 }
Marko Mikulicic 0:c0ecb8bf28eb 15529 case OP_TRY_PUSH_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 15530 case OP_TRY_PUSH_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 15531 case OP_TRY_PUSH_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 15532 case OP_TRY_PUSH_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 15533 eval_try_push(v7, op, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15534 break;
Marko Mikulicic 0:c0ecb8bf28eb 15535 case OP_TRY_POP:
Marko Mikulicic 0:c0ecb8bf28eb 15536 V7_TRY(eval_try_pop(v7));
Marko Mikulicic 0:c0ecb8bf28eb 15537 break;
Marko Mikulicic 0:c0ecb8bf28eb 15538 case OP_AFTER_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 15539 /*
Marko Mikulicic 0:c0ecb8bf28eb 15540 * exited from `finally` block: if some value is currently being
Marko Mikulicic 0:c0ecb8bf28eb 15541 * returned, continue returning it.
Marko Mikulicic 0:c0ecb8bf28eb 15542 *
Marko Mikulicic 0:c0ecb8bf28eb 15543 * Likewise, if some value is currently being thrown, continue
Marko Mikulicic 0:c0ecb8bf28eb 15544 * unwinding stack.
Marko Mikulicic 0:c0ecb8bf28eb 15545 */
Marko Mikulicic 0:c0ecb8bf28eb 15546 if (v7->is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 15547 V7_TRY(
Marko Mikulicic 0:c0ecb8bf28eb 15548 bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/));
Marko Mikulicic 0:c0ecb8bf28eb 15549 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15550 } else if (v7->is_returned) {
Marko Mikulicic 0:c0ecb8bf28eb 15551 V7_TRY(
Marko Mikulicic 0:c0ecb8bf28eb 15552 bcode_perform_return(v7, &r, 0 /*don't take value from stack*/));
Marko Mikulicic 0:c0ecb8bf28eb 15553 break;
Marko Mikulicic 0:c0ecb8bf28eb 15554 } else if (v7->is_breaking) {
Marko Mikulicic 0:c0ecb8bf28eb 15555 bcode_perform_break(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15556 }
Marko Mikulicic 0:c0ecb8bf28eb 15557 break;
Marko Mikulicic 0:c0ecb8bf28eb 15558 case OP_THROW:
Marko Mikulicic 0:c0ecb8bf28eb 15559 V7_TRY(bcode_perform_throw(v7, &r, 1 /*take thrown value*/));
Marko Mikulicic 0:c0ecb8bf28eb 15560 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15561 case OP_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 15562 bcode_perform_break(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15563 break;
Marko Mikulicic 0:c0ecb8bf28eb 15564 case OP_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 15565 v7->is_continuing = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15566 bcode_perform_break(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15567 break;
Marko Mikulicic 0:c0ecb8bf28eb 15568 case OP_ENTER_CATCH: {
Marko Mikulicic 0:c0ecb8bf28eb 15569 /* pop thrown value from stack */
Marko Mikulicic 0:c0ecb8bf28eb 15570 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15571 /* get the name of the thrown value */
Marko Mikulicic 0:c0ecb8bf28eb 15572 v2 = bcode_decode_lit(v7, r.bcode, &r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15573
Marko Mikulicic 0:c0ecb8bf28eb 15574 /*
Marko Mikulicic 0:c0ecb8bf28eb 15575 * create a new stack frame (a "private" one), and set exception
Marko Mikulicic 0:c0ecb8bf28eb 15576 * property on it
Marko Mikulicic 0:c0ecb8bf28eb 15577 */
Marko Mikulicic 0:c0ecb8bf28eb 15578 scope_frame = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15579 BTRY(set_property_v(v7, scope_frame, v2, v1, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15580
Marko Mikulicic 0:c0ecb8bf28eb 15581 /* Push this "private" frame on the call stack */
Marko Mikulicic 0:c0ecb8bf28eb 15582
Marko Mikulicic 0:c0ecb8bf28eb 15583 /* new scope_frame will inherit from the current scope */
Marko Mikulicic 0:c0ecb8bf28eb 15584
Marko Mikulicic 0:c0ecb8bf28eb 15585 obj_prototype_set(v7, get_object_struct(scope_frame),
Marko Mikulicic 0:c0ecb8bf28eb 15586 get_object_struct(get_scope(v7)));
Marko Mikulicic 0:c0ecb8bf28eb 15587
Marko Mikulicic 0:c0ecb8bf28eb 15588 /*
Marko Mikulicic 0:c0ecb8bf28eb 15589 * Create new `call_frame` which will replace `v7->call_stack`.
Marko Mikulicic 0:c0ecb8bf28eb 15590 */
Marko Mikulicic 0:c0ecb8bf28eb 15591 append_call_frame_private(v7, scope_frame);
Marko Mikulicic 0:c0ecb8bf28eb 15592
Marko Mikulicic 0:c0ecb8bf28eb 15593 break;
Marko Mikulicic 0:c0ecb8bf28eb 15594 }
Marko Mikulicic 0:c0ecb8bf28eb 15595 case OP_EXIT_CATCH: {
Marko Mikulicic 0:c0ecb8bf28eb 15596 v7_call_frame_mask_t frame_type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 15597 /* unwind 1 frame */
Marko Mikulicic 0:c0ecb8bf28eb 15598 frame_type_mask = unwind_stack_1level(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15599 /* make sure the unwound frame is a "private" frame */
Marko Mikulicic 0:c0ecb8bf28eb 15600 assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 15601 #if defined(NDEBUG)
Marko Mikulicic 0:c0ecb8bf28eb 15602 (void) frame_type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 15603 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15604 break;
Marko Mikulicic 0:c0ecb8bf28eb 15605 }
Marko Mikulicic 0:c0ecb8bf28eb 15606 default:
Marko Mikulicic 0:c0ecb8bf28eb 15607 BTRY(v7_throwf(v7, INTERNAL_ERROR, "Unknown opcode: %d", (int) op));
Marko Mikulicic 0:c0ecb8bf28eb 15608 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15609 }
Marko Mikulicic 0:c0ecb8bf28eb 15610
Marko Mikulicic 0:c0ecb8bf28eb 15611 op_done:
Marko Mikulicic 0:c0ecb8bf28eb 15612 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 15613 /* print current stack state */
Marko Mikulicic 0:c0ecb8bf28eb 15614 {
Marko Mikulicic 0:c0ecb8bf28eb 15615 char buf[40];
Marko Mikulicic 0:c0ecb8bf28eb 15616 char *str = v7_stringify(v7, TOS(), buf, sizeof(buf), V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 15617 fprintf(stderr, " stack size: %u, TOS: '%s'\n",
Marko Mikulicic 0:c0ecb8bf28eb 15618 (unsigned int) (v7->stack.len / sizeof(val_t)), str);
Marko Mikulicic 0:c0ecb8bf28eb 15619 if (str != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 15620 free(str);
Marko Mikulicic 0:c0ecb8bf28eb 15621 }
Marko Mikulicic 0:c0ecb8bf28eb 15622
Marko Mikulicic 0:c0ecb8bf28eb 15623 #ifdef V7_BCODE_TRACE_STACK
Marko Mikulicic 0:c0ecb8bf28eb 15624 {
Marko Mikulicic 0:c0ecb8bf28eb 15625 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 15626 for (i = 0; i < (v7->stack.len / sizeof(val_t)); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 15627 char *str = v7_stringify(v7, stack_at(&v7->stack, i), buf,
Marko Mikulicic 0:c0ecb8bf28eb 15628 sizeof(buf), V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 15629
Marko Mikulicic 0:c0ecb8bf28eb 15630 fprintf(stderr, " #: '%s'\n", str);
Marko Mikulicic 0:c0ecb8bf28eb 15631
Marko Mikulicic 0:c0ecb8bf28eb 15632 if (str != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 15633 free(str);
Marko Mikulicic 0:c0ecb8bf28eb 15634 }
Marko Mikulicic 0:c0ecb8bf28eb 15635 }
Marko Mikulicic 0:c0ecb8bf28eb 15636 }
Marko Mikulicic 0:c0ecb8bf28eb 15637 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15638 }
Marko Mikulicic 0:c0ecb8bf28eb 15639 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15640 if (r.need_inc_ops) {
Marko Mikulicic 0:c0ecb8bf28eb 15641 r.ops++;
Marko Mikulicic 0:c0ecb8bf28eb 15642 }
Marko Mikulicic 0:c0ecb8bf28eb 15643 }
Marko Mikulicic 0:c0ecb8bf28eb 15644
Marko Mikulicic 0:c0ecb8bf28eb 15645 /* implicit return */
Marko Mikulicic 0:c0ecb8bf28eb 15646 if (v7->call_stack != v7->bottom_call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 15647 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 15648 fprintf(stderr, "return implicitly\n");
Marko Mikulicic 0:c0ecb8bf28eb 15649 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15650 bcode_adjust_retval(v7, 0 /*implicit return*/);
Marko Mikulicic 0:c0ecb8bf28eb 15651 V7_TRY(bcode_perform_return(v7, &r, 1));
Marko Mikulicic 0:c0ecb8bf28eb 15652 goto restart;
Marko Mikulicic 0:c0ecb8bf28eb 15653 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15654 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 15655 const char *s = (get_scope(v7) != v7->vals.global_object)
Marko Mikulicic 0:c0ecb8bf28eb 15656 ? "not global object"
Marko Mikulicic 0:c0ecb8bf28eb 15657 : "global object";
Marko Mikulicic 0:c0ecb8bf28eb 15658 fprintf(stderr, "reached bottom_call_frame (%s)\n", s);
Marko Mikulicic 0:c0ecb8bf28eb 15659 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15660 }
Marko Mikulicic 0:c0ecb8bf28eb 15661
Marko Mikulicic 0:c0ecb8bf28eb 15662 clean:
Marko Mikulicic 0:c0ecb8bf28eb 15663
Marko Mikulicic 0:c0ecb8bf28eb 15664 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 15665 /*
Marko Mikulicic 0:c0ecb8bf28eb 15666 * bcode evaluated successfully. Make sure try stack is empty.
Marko Mikulicic 0:c0ecb8bf28eb 15667 * (data stack will be checked below, in `clean`)
Marko Mikulicic 0:c0ecb8bf28eb 15668 */
Marko Mikulicic 0:c0ecb8bf28eb 15669 #ifndef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 15670 {
Marko Mikulicic 0:c0ecb8bf28eb 15671 unsigned long try_stack_len =
Marko Mikulicic 0:c0ecb8bf28eb 15672 v7_array_length(v7, find_call_frame_private(v7)->vals.try_stack);
Marko Mikulicic 0:c0ecb8bf28eb 15673 if (try_stack_len != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15674 fprintf(stderr, "try_stack_len=%lu, should be 0\n", try_stack_len);
Marko Mikulicic 0:c0ecb8bf28eb 15675 }
Marko Mikulicic 0:c0ecb8bf28eb 15676 assert(try_stack_len == 0);
Marko Mikulicic 0:c0ecb8bf28eb 15677 }
Marko Mikulicic 0:c0ecb8bf28eb 15678 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15679
Marko Mikulicic 0:c0ecb8bf28eb 15680 /* get the value returned from the evaluated script */
Marko Mikulicic 0:c0ecb8bf28eb 15681 *_res = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15682 }
Marko Mikulicic 0:c0ecb8bf28eb 15683
Marko Mikulicic 0:c0ecb8bf28eb 15684 assert(v7->bottom_call_frame == v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 15685 unwind_stack_1level(v7, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15686
Marko Mikulicic 0:c0ecb8bf28eb 15687 v7->bottom_call_frame = saved_bottom_call_frame;
Marko Mikulicic 0:c0ecb8bf28eb 15688
Marko Mikulicic 0:c0ecb8bf28eb 15689 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 15690 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 15691 }
Marko Mikulicic 0:c0ecb8bf28eb 15692
Marko Mikulicic 0:c0ecb8bf28eb 15693 /*
Marko Mikulicic 0:c0ecb8bf28eb 15694 * TODO(dfrank) this function is probably too overloaded: it handles both
Marko Mikulicic 0:c0ecb8bf28eb 15695 * `v7_exec` and `v7_apply`. Read below why it's written this way, but it's
Marko Mikulicic 0:c0ecb8bf28eb 15696 * probably a good idea to factor out common functionality in some other
Marko Mikulicic 0:c0ecb8bf28eb 15697 * function.
Marko Mikulicic 0:c0ecb8bf28eb 15698 *
Marko Mikulicic 0:c0ecb8bf28eb 15699 * If `src` is not `NULL`, then we behave in favour of `v7_exec`: parse,
Marko Mikulicic 0:c0ecb8bf28eb 15700 * compile, and evaluate the script. The `func` and `args` are ignored.
Marko Mikulicic 0:c0ecb8bf28eb 15701 *
Marko Mikulicic 0:c0ecb8bf28eb 15702 * If, however, `src` is `NULL`, then we behave in favour of `v7_apply`: we
Marko Mikulicic 0:c0ecb8bf28eb 15703 * call the provided `func` with `args`. But unlike interpreter, we can't just
Marko Mikulicic 0:c0ecb8bf28eb 15704 * call the provided function: we need to setup environment for this call.
Marko Mikulicic 0:c0ecb8bf28eb 15705 *
Marko Mikulicic 0:c0ecb8bf28eb 15706 * Currently, we just quickly generate the "wrapper" bcode for the function.
Marko Mikulicic 0:c0ecb8bf28eb 15707 * This wrapper bcode looks like this:
Marko Mikulicic 0:c0ecb8bf28eb 15708 *
Marko Mikulicic 0:c0ecb8bf28eb 15709 * OP_PUSH_UNDEFINED
Marko Mikulicic 0:c0ecb8bf28eb 15710 * OP_PUSH_LIT # push this
Marko Mikulicic 0:c0ecb8bf28eb 15711 * OP_PUSH_LIT # push function
Marko Mikulicic 0:c0ecb8bf28eb 15712 * OP_PUSH_LIT # push arg1
Marko Mikulicic 0:c0ecb8bf28eb 15713 * OP_PUSH_LIT # push arg2
Marko Mikulicic 0:c0ecb8bf28eb 15714 * ...
Marko Mikulicic 0:c0ecb8bf28eb 15715 * OP_PUSH_LIT # push argN
Marko Mikulicic 0:c0ecb8bf28eb 15716 * OP_CALL(N) # call function with N arguments
Marko Mikulicic 0:c0ecb8bf28eb 15717 * OP_SWAP_DROP
Marko Mikulicic 0:c0ecb8bf28eb 15718 *
Marko Mikulicic 0:c0ecb8bf28eb 15719 * and then, bcode evaluator proceeds with this code.
Marko Mikulicic 0:c0ecb8bf28eb 15720 *
Marko Mikulicic 0:c0ecb8bf28eb 15721 * In fact, both cases (eval or apply) are quite similar: we should prepare
Marko Mikulicic 0:c0ecb8bf28eb 15722 * environment for the bcode evaluation in exactly the same way, and the only
Marko Mikulicic 0:c0ecb8bf28eb 15723 * different part is where we get the bcode from. This is why that
Marko Mikulicic 0:c0ecb8bf28eb 15724 * functionality is baked in the single function, but it would be good to make
Marko Mikulicic 0:c0ecb8bf28eb 15725 * it suck less.
Marko Mikulicic 0:c0ecb8bf28eb 15726 */
Marko Mikulicic 0:c0ecb8bf28eb 15727 V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 15728 const char *filename, val_t func, val_t args,
Marko Mikulicic 0:c0ecb8bf28eb 15729 val_t this_object, int is_json, int fr,
Marko Mikulicic 0:c0ecb8bf28eb 15730 uint8_t is_constructor, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 15731 #if defined(V7_BCODE_TRACE_SRC)
Marko Mikulicic 0:c0ecb8bf28eb 15732 fprintf(stderr, "src:'%s'\n", src);
Marko Mikulicic 0:c0ecb8bf28eb 15733 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15734
Marko Mikulicic 0:c0ecb8bf28eb 15735 /* TODO(mkm): use GC pool */
Marko Mikulicic 0:c0ecb8bf28eb 15736 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15737 struct ast *a = (struct ast *) malloc(sizeof(struct ast));
Marko Mikulicic 0:c0ecb8bf28eb 15738 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15739 size_t saved_stack_len = v7->stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 15740 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 15741 val_t _res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15742 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15743 struct bcode *bcode = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15744 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 15745 struct stack_track_ctx stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 15746 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15747 struct {
Marko Mikulicic 0:c0ecb8bf28eb 15748 unsigned noopt : 1;
Marko Mikulicic 0:c0ecb8bf28eb 15749 unsigned line_no_reset : 1;
Marko Mikulicic 0:c0ecb8bf28eb 15750 } flags = {0, 0};
Marko Mikulicic 0:c0ecb8bf28eb 15751
Marko Mikulicic 0:c0ecb8bf28eb 15752 (void) filename;
Marko Mikulicic 0:c0ecb8bf28eb 15753
Marko Mikulicic 0:c0ecb8bf28eb 15754 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 15755 v7_stack_track_start(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15756 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15757
Marko Mikulicic 0:c0ecb8bf28eb 15758 tmp_stack_push(&tf, &func);
Marko Mikulicic 0:c0ecb8bf28eb 15759 tmp_stack_push(&tf, &args);
Marko Mikulicic 0:c0ecb8bf28eb 15760 tmp_stack_push(&tf, &this_object);
Marko Mikulicic 0:c0ecb8bf28eb 15761 tmp_stack_push(&tf, &_res);
Marko Mikulicic 0:c0ecb8bf28eb 15762
Marko Mikulicic 0:c0ecb8bf28eb 15763 /* init new bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15764 bcode = (struct bcode *) calloc(1, sizeof(*bcode));
Marko Mikulicic 0:c0ecb8bf28eb 15765
Marko Mikulicic 0:c0ecb8bf28eb 15766 bcode_init(bcode,
Marko Mikulicic 0:c0ecb8bf28eb 15767 #ifndef V7_FORCE_STRICT_MODE
Marko Mikulicic 0:c0ecb8bf28eb 15768 0,
Marko Mikulicic 0:c0ecb8bf28eb 15769 #else
Marko Mikulicic 0:c0ecb8bf28eb 15770 1,
Marko Mikulicic 0:c0ecb8bf28eb 15771 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15772 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 15773 filename ? shdata_create_from_string(filename) : NULL,
Marko Mikulicic 0:c0ecb8bf28eb 15774 #else
Marko Mikulicic 0:c0ecb8bf28eb 15775 NULL,
Marko Mikulicic 0:c0ecb8bf28eb 15776 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15777 0 /*filename not in ROM*/
Marko Mikulicic 0:c0ecb8bf28eb 15778 );
Marko Mikulicic 0:c0ecb8bf28eb 15779
Marko Mikulicic 0:c0ecb8bf28eb 15780 retain_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15781 own_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15782
Marko Mikulicic 0:c0ecb8bf28eb 15783 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15784 ast_init(a, 0);
Marko Mikulicic 0:c0ecb8bf28eb 15785 a->refcnt = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15786 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15787
Marko Mikulicic 0:c0ecb8bf28eb 15788 if (src != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15789 /* Caller provided some source code, so, handle it somehow */
Marko Mikulicic 0:c0ecb8bf28eb 15790
Marko Mikulicic 0:c0ecb8bf28eb 15791 flags.line_no_reset = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15792
Marko Mikulicic 0:c0ecb8bf28eb 15793 if (src_len >= sizeof(BIN_BCODE_SIGNATURE) &&
Marko Mikulicic 0:c0ecb8bf28eb 15794 strncmp(BIN_BCODE_SIGNATURE, src, sizeof(BIN_BCODE_SIGNATURE)) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15795 /* we have a serialized bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15796
Marko Mikulicic 0:c0ecb8bf28eb 15797 bcode_deserialize(v7, bcode, src + sizeof(BIN_BCODE_SIGNATURE));
Marko Mikulicic 0:c0ecb8bf28eb 15798
Marko Mikulicic 0:c0ecb8bf28eb 15799 /*
Marko Mikulicic 0:c0ecb8bf28eb 15800 * Currently, we only support serialized bcode that is stored in some
Marko Mikulicic 0:c0ecb8bf28eb 15801 * mmapped memory. Otherwise, we don't yet have any mechanism to free
Marko Mikulicic 0:c0ecb8bf28eb 15802 * this memory at the appropriate time.
Marko Mikulicic 0:c0ecb8bf28eb 15803 */
Marko Mikulicic 0:c0ecb8bf28eb 15804
Marko Mikulicic 0:c0ecb8bf28eb 15805 /*
Marko Mikulicic 0:c0ecb8bf28eb 15806 * TODO(dfrank): currently, we remove this assert, and introduce memory
Marko Mikulicic 0:c0ecb8bf28eb 15807 * leak. We need to support that properly.
Marko Mikulicic 0:c0ecb8bf28eb 15808 */
Marko Mikulicic 0:c0ecb8bf28eb 15809 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 15810 assert(fr == 0);
Marko Mikulicic 0:c0ecb8bf28eb 15811 #else
Marko Mikulicic 0:c0ecb8bf28eb 15812 if (fr) {
Marko Mikulicic 0:c0ecb8bf28eb 15813 fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15814 }
Marko Mikulicic 0:c0ecb8bf28eb 15815 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15816 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15817 /* Maybe regular JavaScript source or binary AST data */
Marko Mikulicic 0:c0ecb8bf28eb 15818 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15819
Marko Mikulicic 0:c0ecb8bf28eb 15820 if (src_len >= sizeof(BIN_AST_SIGNATURE) &&
Marko Mikulicic 0:c0ecb8bf28eb 15821 strncmp(BIN_AST_SIGNATURE, src, sizeof(BIN_AST_SIGNATURE)) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15822 /* we have binary AST data */
Marko Mikulicic 0:c0ecb8bf28eb 15823
Marko Mikulicic 0:c0ecb8bf28eb 15824 if (fr == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15825 /* Unmanaged memory, usually rom or mmapped flash */
Marko Mikulicic 0:c0ecb8bf28eb 15826 mbuf_free(&a->mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 15827 a->mbuf.buf = (char *) (src + sizeof(BIN_AST_SIGNATURE));
Marko Mikulicic 0:c0ecb8bf28eb 15828 a->mbuf.size = a->mbuf.len = src_len - sizeof(BIN_AST_SIGNATURE);
Marko Mikulicic 0:c0ecb8bf28eb 15829 a->refcnt++; /* prevent freeing */
Marko Mikulicic 0:c0ecb8bf28eb 15830 flags.noopt = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15831 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15832 mbuf_append(&a->mbuf, src + sizeof(BIN_AST_SIGNATURE),
Marko Mikulicic 0:c0ecb8bf28eb 15833 src_len - sizeof(BIN_AST_SIGNATURE));
Marko Mikulicic 0:c0ecb8bf28eb 15834 }
Marko Mikulicic 0:c0ecb8bf28eb 15835 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15836 /* we have regular JavaScript source, so, parse it */
Marko Mikulicic 0:c0ecb8bf28eb 15837 V7_TRY(parse(v7, a, src, src_len, is_json));
Marko Mikulicic 0:c0ecb8bf28eb 15838 }
Marko Mikulicic 0:c0ecb8bf28eb 15839
Marko Mikulicic 0:c0ecb8bf28eb 15840 /* we now have binary AST, let's compile it */
Marko Mikulicic 0:c0ecb8bf28eb 15841
Marko Mikulicic 0:c0ecb8bf28eb 15842 if (!flags.noopt) {
Marko Mikulicic 0:c0ecb8bf28eb 15843 ast_optimize(a);
Marko Mikulicic 0:c0ecb8bf28eb 15844 }
Marko Mikulicic 0:c0ecb8bf28eb 15845 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 15846 v7->function_arena_ast_size += a->mbuf.size;
Marko Mikulicic 0:c0ecb8bf28eb 15847 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15848
Marko Mikulicic 0:c0ecb8bf28eb 15849 if (v7_is_undefined(this_object)) {
Marko Mikulicic 0:c0ecb8bf28eb 15850 this_object = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 15851 }
Marko Mikulicic 0:c0ecb8bf28eb 15852
Marko Mikulicic 0:c0ecb8bf28eb 15853 if (!is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 15854 V7_TRY(compile_script(v7, a, bcode));
Marko Mikulicic 0:c0ecb8bf28eb 15855 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15856 ast_off_t pos = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15857 V7_TRY(compile_expr(v7, a, &pos, bcode));
Marko Mikulicic 0:c0ecb8bf28eb 15858 }
Marko Mikulicic 0:c0ecb8bf28eb 15859 #else /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15860 (void) is_json;
Marko Mikulicic 0:c0ecb8bf28eb 15861 /* Parsing JavaScript code is disabled */
Marko Mikulicic 0:c0ecb8bf28eb 15862 rcode = v7_throwf(v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 15863 "Parsing JS code is disabled by V7_NO_COMPILER");
Marko Mikulicic 0:c0ecb8bf28eb 15864 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 15865 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15866 }
Marko Mikulicic 0:c0ecb8bf28eb 15867
Marko Mikulicic 0:c0ecb8bf28eb 15868 } else if (is_js_function(func)) {
Marko Mikulicic 0:c0ecb8bf28eb 15869 /*
Marko Mikulicic 0:c0ecb8bf28eb 15870 * Caller did not provide source code, so, assume we should call
Marko Mikulicic 0:c0ecb8bf28eb 15871 * provided function. Here, we prepare "wrapper" bcode.
Marko Mikulicic 0:c0ecb8bf28eb 15872 */
Marko Mikulicic 0:c0ecb8bf28eb 15873
Marko Mikulicic 0:c0ecb8bf28eb 15874 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 15875 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 15876 int args_cnt = v7_array_length(v7, args);
Marko Mikulicic 0:c0ecb8bf28eb 15877
Marko Mikulicic 0:c0ecb8bf28eb 15878 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15879
Marko Mikulicic 0:c0ecb8bf28eb 15880 bcode_op(&bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 15881
Marko Mikulicic 0:c0ecb8bf28eb 15882 /* push `this` */
Marko Mikulicic 0:c0ecb8bf28eb 15883 lit = bcode_add_lit(&bbuilder, this_object);
Marko Mikulicic 0:c0ecb8bf28eb 15884 bcode_push_lit(&bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 15885
Marko Mikulicic 0:c0ecb8bf28eb 15886 /* push func literal */
Marko Mikulicic 0:c0ecb8bf28eb 15887 lit = bcode_add_lit(&bbuilder, func);
Marko Mikulicic 0:c0ecb8bf28eb 15888 bcode_push_lit(&bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 15889
Marko Mikulicic 0:c0ecb8bf28eb 15890 /* push args */
Marko Mikulicic 0:c0ecb8bf28eb 15891 {
Marko Mikulicic 0:c0ecb8bf28eb 15892 int i;
Marko Mikulicic 0:c0ecb8bf28eb 15893 for (i = 0; i < args_cnt; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 15894 lit = bcode_add_lit(&bbuilder, v7_array_get(v7, args, i));
Marko Mikulicic 0:c0ecb8bf28eb 15895 bcode_push_lit(&bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 15896 }
Marko Mikulicic 0:c0ecb8bf28eb 15897 }
Marko Mikulicic 0:c0ecb8bf28eb 15898
Marko Mikulicic 0:c0ecb8bf28eb 15899 bcode_op(&bbuilder, OP_CALL);
Marko Mikulicic 0:c0ecb8bf28eb 15900 /* TODO(dfrank): check if args <= 0x7f */
Marko Mikulicic 0:c0ecb8bf28eb 15901 bcode_op(&bbuilder, (uint8_t) args_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 15902
Marko Mikulicic 0:c0ecb8bf28eb 15903 bcode_op(&bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 15904
Marko Mikulicic 0:c0ecb8bf28eb 15905 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 15906 } else if (is_cfunction_lite(func) || is_cfunction_obj(v7, func)) {
Marko Mikulicic 0:c0ecb8bf28eb 15907 /* call cfunction */
Marko Mikulicic 0:c0ecb8bf28eb 15908
Marko Mikulicic 0:c0ecb8bf28eb 15909 V7_TRY(call_cfunction(v7, func, this_object, args, is_constructor, &_res));
Marko Mikulicic 0:c0ecb8bf28eb 15910
Marko Mikulicic 0:c0ecb8bf28eb 15911 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 15912 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15913 /* value is not a function */
Marko Mikulicic 0:c0ecb8bf28eb 15914 V7_TRY(v7_throwf(v7, TYPE_ERROR, "value is not a function"));
Marko Mikulicic 0:c0ecb8bf28eb 15915 }
Marko Mikulicic 0:c0ecb8bf28eb 15916
Marko Mikulicic 0:c0ecb8bf28eb 15917 /* We now have bcode to evaluate; proceed to it */
Marko Mikulicic 0:c0ecb8bf28eb 15918
Marko Mikulicic 0:c0ecb8bf28eb 15919 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15920 /*
Marko Mikulicic 0:c0ecb8bf28eb 15921 * Before we evaluate bcode, we can safely release AST since it's not needed
Marko Mikulicic 0:c0ecb8bf28eb 15922 * anymore. Note that there's no leak here: if we `goto clean` from somewhere
Marko Mikulicic 0:c0ecb8bf28eb 15923 * above, we'll anyway release the AST under `clean` as well.
Marko Mikulicic 0:c0ecb8bf28eb 15924 */
Marko Mikulicic 0:c0ecb8bf28eb 15925 release_ast(v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 15926 a = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15927 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15928
Marko Mikulicic 0:c0ecb8bf28eb 15929 /* Evaluate bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15930 V7_TRY(eval_bcode(v7, bcode, this_object, flags.line_no_reset, &_res));
Marko Mikulicic 0:c0ecb8bf28eb 15931
Marko Mikulicic 0:c0ecb8bf28eb 15932 clean:
Marko Mikulicic 0:c0ecb8bf28eb 15933
Marko Mikulicic 0:c0ecb8bf28eb 15934 /* free `src` if needed */
Marko Mikulicic 0:c0ecb8bf28eb 15935 /*
Marko Mikulicic 0:c0ecb8bf28eb 15936 * TODO(dfrank) : free it above, just after parsing, and make sure you use
Marko Mikulicic 0:c0ecb8bf28eb 15937 * V7_TRY2() with custom label instead of V7_TRY()
Marko Mikulicic 0:c0ecb8bf28eb 15938 */
Marko Mikulicic 0:c0ecb8bf28eb 15939 if (src != NULL && fr) {
Marko Mikulicic 0:c0ecb8bf28eb 15940 free((void *) src);
Marko Mikulicic 0:c0ecb8bf28eb 15941 }
Marko Mikulicic 0:c0ecb8bf28eb 15942
Marko Mikulicic 0:c0ecb8bf28eb 15943 /* disown and release current bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15944 disown_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15945 release_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15946 bcode = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15947
Marko Mikulicic 0:c0ecb8bf28eb 15948 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 15949 /* some exception happened. */
Marko Mikulicic 0:c0ecb8bf28eb 15950 _res = v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 15951
Marko Mikulicic 0:c0ecb8bf28eb 15952 /*
Marko Mikulicic 0:c0ecb8bf28eb 15953 * if this is a top-level bcode, clear thrown error from the v7 context
Marko Mikulicic 0:c0ecb8bf28eb 15954 *
Marko Mikulicic 0:c0ecb8bf28eb 15955 * TODO(dfrank): do we really need to do this?
Marko Mikulicic 0:c0ecb8bf28eb 15956 *
Marko Mikulicic 0:c0ecb8bf28eb 15957 * If we don't clear the error, then we should clear it manually after each
Marko Mikulicic 0:c0ecb8bf28eb 15958 * call to v7_exec() or friends; otherwise, all the following calls will
Marko Mikulicic 0:c0ecb8bf28eb 15959 * see this error.
Marko Mikulicic 0:c0ecb8bf28eb 15960 *
Marko Mikulicic 0:c0ecb8bf28eb 15961 * On the other hand, user would still need to clear the error if he calls
Marko Mikulicic 0:c0ecb8bf28eb 15962 * v7_exec() from some cfunction. So, currently, sometimes we don't need
Marko Mikulicic 0:c0ecb8bf28eb 15963 * to clear the error, and sometimes we do, which is confusing.
Marko Mikulicic 0:c0ecb8bf28eb 15964 */
Marko Mikulicic 0:c0ecb8bf28eb 15965 if (v7->act_bcodes.len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15966 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15967 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15968 }
Marko Mikulicic 0:c0ecb8bf28eb 15969 }
Marko Mikulicic 0:c0ecb8bf28eb 15970
Marko Mikulicic 0:c0ecb8bf28eb 15971 /*
Marko Mikulicic 0:c0ecb8bf28eb 15972 * Data stack should have the same length as it was before evaluating script.
Marko Mikulicic 0:c0ecb8bf28eb 15973 */
Marko Mikulicic 0:c0ecb8bf28eb 15974 if (v7->stack.len != saved_stack_len) {
Marko Mikulicic 0:c0ecb8bf28eb 15975 fprintf(stderr, "len=%d, saved=%d\n", (int) v7->stack.len,
Marko Mikulicic 0:c0ecb8bf28eb 15976 (int) saved_stack_len);
Marko Mikulicic 0:c0ecb8bf28eb 15977 }
Marko Mikulicic 0:c0ecb8bf28eb 15978 assert(v7->stack.len == saved_stack_len);
Marko Mikulicic 0:c0ecb8bf28eb 15979
Marko Mikulicic 0:c0ecb8bf28eb 15980 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15981 /*
Marko Mikulicic 0:c0ecb8bf28eb 15982 * release AST if needed (normally, it's already released above, before
Marko Mikulicic 0:c0ecb8bf28eb 15983 * bcode evaluation)
Marko Mikulicic 0:c0ecb8bf28eb 15984 */
Marko Mikulicic 0:c0ecb8bf28eb 15985 if (a != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15986 release_ast(v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 15987 a = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15988 }
Marko Mikulicic 0:c0ecb8bf28eb 15989 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15990
Marko Mikulicic 0:c0ecb8bf28eb 15991 if (is_constructor && !v7_is_object(_res)) {
Marko Mikulicic 0:c0ecb8bf28eb 15992 /* constructor returned non-object: replace it with `this` */
Marko Mikulicic 0:c0ecb8bf28eb 15993 _res = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15994 }
Marko Mikulicic 0:c0ecb8bf28eb 15995
Marko Mikulicic 0:c0ecb8bf28eb 15996 /* Provide the caller with the result, if asked to do so */
Marko Mikulicic 0:c0ecb8bf28eb 15997 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15998 *res = _res;
Marko Mikulicic 0:c0ecb8bf28eb 15999 }
Marko Mikulicic 0:c0ecb8bf28eb 16000
Marko Mikulicic 0:c0ecb8bf28eb 16001 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 16002 {
Marko Mikulicic 0:c0ecb8bf28eb 16003 int diff = v7_stack_track_end(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 16004 if (diff > v7->stack_stat[V7_STACK_STAT_EXEC]) {
Marko Mikulicic 0:c0ecb8bf28eb 16005 v7->stack_stat[V7_STACK_STAT_EXEC] = diff;
Marko Mikulicic 0:c0ecb8bf28eb 16006 }
Marko Mikulicic 0:c0ecb8bf28eb 16007 }
Marko Mikulicic 0:c0ecb8bf28eb 16008 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16009
Marko Mikulicic 0:c0ecb8bf28eb 16010 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 16011 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 16012 }
Marko Mikulicic 0:c0ecb8bf28eb 16013
Marko Mikulicic 0:c0ecb8bf28eb 16014 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 16015 V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 16016 v7_val_t args, uint8_t is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 16017 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16018 return b_exec(v7, NULL, 0, NULL, func, args, this_obj, 0, 0, is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 16019 res);
Marko Mikulicic 0:c0ecb8bf28eb 16020 }
Marko Mikulicic 0:c0ecb8bf28eb 16021 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16022 #line 1 "v7/src/core.c"
Marko Mikulicic 0:c0ecb8bf28eb 16023 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16024 /*
Marko Mikulicic 0:c0ecb8bf28eb 16025 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16026 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16027 */
Marko Mikulicic 0:c0ecb8bf28eb 16028
Marko Mikulicic 0:c0ecb8bf28eb 16029 /* Amalgamated: #include "v7/builtin/builtin.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16030 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16031 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16032 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16033 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16034 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16035 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16036 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16037 /* Amalgamated: #include "v7/src/stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16038 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16039 /* Amalgamated: #include "v7/src/heapusage.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16040 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16041
Marko Mikulicic 0:c0ecb8bf28eb 16042 #ifdef V7_THAW
Marko Mikulicic 0:c0ecb8bf28eb 16043 extern struct v7_vals *fr_vals;
Marko Mikulicic 0:c0ecb8bf28eb 16044 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16045
Marko Mikulicic 0:c0ecb8bf28eb 16046 #ifdef HAS_V7_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 16047 double _v7_infinity;
Marko Mikulicic 0:c0ecb8bf28eb 16048 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16049
Marko Mikulicic 0:c0ecb8bf28eb 16050 #ifdef HAS_V7_NAN
Marko Mikulicic 0:c0ecb8bf28eb 16051 double _v7_nan;
Marko Mikulicic 0:c0ecb8bf28eb 16052 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16053
Marko Mikulicic 0:c0ecb8bf28eb 16054 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 16055 struct v7 *v7_head = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16056 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16057
Marko Mikulicic 0:c0ecb8bf28eb 16058 static void generic_object_destructor(struct v7 *v7, void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 16059 struct v7_generic_object *o = (struct v7_generic_object *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 16060 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16061 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 16062
Marko Mikulicic 0:c0ecb8bf28eb 16063 /* TODO(mkm): make regexp use user data API */
Marko Mikulicic 0:c0ecb8bf28eb 16064 p = v7_get_own_property2(v7, v7_object_to_value(&o->base), "", 0,
Marko Mikulicic 0:c0ecb8bf28eb 16065 _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 16066
Marko Mikulicic 0:c0ecb8bf28eb 16067 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 16068 if (p != NULL && (p->value & V7_TAG_MASK) == V7_TAG_REGEXP) {
Marko Mikulicic 0:c0ecb8bf28eb 16069 struct v7_regexp *rp = (struct v7_regexp *) get_ptr(p->value);
Marko Mikulicic 0:c0ecb8bf28eb 16070 v7_disown(v7, &rp->regexp_string);
Marko Mikulicic 0:c0ecb8bf28eb 16071 slre_free(rp->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 16072 free(rp);
Marko Mikulicic 0:c0ecb8bf28eb 16073 }
Marko Mikulicic 0:c0ecb8bf28eb 16074 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16075
Marko Mikulicic 0:c0ecb8bf28eb 16076 if (o->base.attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 16077 if (p != NULL &&
Marko Mikulicic 0:c0ecb8bf28eb 16078 ((abuf = (struct mbuf *) v7_get_ptr(v7, p->value)) != NULL)) {
Marko Mikulicic 0:c0ecb8bf28eb 16079 mbuf_free(abuf);
Marko Mikulicic 0:c0ecb8bf28eb 16080 free(abuf);
Marko Mikulicic 0:c0ecb8bf28eb 16081 }
Marko Mikulicic 0:c0ecb8bf28eb 16082 }
Marko Mikulicic 0:c0ecb8bf28eb 16083
Marko Mikulicic 0:c0ecb8bf28eb 16084 if (o->base.attributes & V7_OBJ_HAS_DESTRUCTOR) {
Marko Mikulicic 0:c0ecb8bf28eb 16085 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16086 for (p = o->base.properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 16087 if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) {
Marko Mikulicic 0:c0ecb8bf28eb 16088 if (v7_is_foreign(p->name)) {
Marko Mikulicic 0:c0ecb8bf28eb 16089 v7_destructor_cb_t *cb =
Marko Mikulicic 0:c0ecb8bf28eb 16090 (v7_destructor_cb_t *) v7_get_ptr(v7, p->name);
Marko Mikulicic 0:c0ecb8bf28eb 16091 cb(v7, v7_get_ptr(v7, p->value));
Marko Mikulicic 0:c0ecb8bf28eb 16092 }
Marko Mikulicic 0:c0ecb8bf28eb 16093 break;
Marko Mikulicic 0:c0ecb8bf28eb 16094 }
Marko Mikulicic 0:c0ecb8bf28eb 16095 }
Marko Mikulicic 0:c0ecb8bf28eb 16096 }
Marko Mikulicic 0:c0ecb8bf28eb 16097
Marko Mikulicic 0:c0ecb8bf28eb 16098 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16099 o->base.entity_id_base = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16100 o->base.entity_id_spec = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16101 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16102 }
Marko Mikulicic 0:c0ecb8bf28eb 16103
Marko Mikulicic 0:c0ecb8bf28eb 16104 static void function_destructor(struct v7 *v7, void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 16105 struct v7_js_function *f = (struct v7_js_function *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 16106 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16107 if (f == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 16108
Marko Mikulicic 0:c0ecb8bf28eb 16109 if (f->bcode != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16110 release_bcode(v7, f->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16111 }
Marko Mikulicic 0:c0ecb8bf28eb 16112
Marko Mikulicic 0:c0ecb8bf28eb 16113 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16114 f->base.entity_id_base = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16115 f->base.entity_id_spec = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16116 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16117 }
Marko Mikulicic 0:c0ecb8bf28eb 16118
Marko Mikulicic 0:c0ecb8bf28eb 16119 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16120 static void property_destructor(struct v7 *v7, void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 16121 struct v7_property *p = (struct v7_property *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 16122 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16123 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 16124
Marko Mikulicic 0:c0ecb8bf28eb 16125 p->entity_id = V7_ENTITY_ID_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16126 }
Marko Mikulicic 0:c0ecb8bf28eb 16127 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16128
Marko Mikulicic 0:c0ecb8bf28eb 16129 struct v7 *v7_create(void) {
Marko Mikulicic 0:c0ecb8bf28eb 16130 struct v7_create_opts opts;
Marko Mikulicic 0:c0ecb8bf28eb 16131 memset(&opts, 0, sizeof(opts));
Marko Mikulicic 0:c0ecb8bf28eb 16132 return v7_create_opt(opts);
Marko Mikulicic 0:c0ecb8bf28eb 16133 }
Marko Mikulicic 0:c0ecb8bf28eb 16134
Marko Mikulicic 0:c0ecb8bf28eb 16135 struct v7 *v7_create_opt(struct v7_create_opts opts) {
Marko Mikulicic 0:c0ecb8bf28eb 16136 struct v7 *v7 = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16137 char z = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16138
Marko Mikulicic 0:c0ecb8bf28eb 16139 #if defined(HAS_V7_INFINITY) || defined(HAS_V7_NAN)
Marko Mikulicic 0:c0ecb8bf28eb 16140 double zero = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 16141 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16142
Marko Mikulicic 0:c0ecb8bf28eb 16143 #ifdef HAS_V7_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 16144 _v7_infinity = 1.0 / zero;
Marko Mikulicic 0:c0ecb8bf28eb 16145 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16146 #ifdef HAS_V7_NAN
Marko Mikulicic 0:c0ecb8bf28eb 16147 _v7_nan = zero / zero;
Marko Mikulicic 0:c0ecb8bf28eb 16148 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16149
Marko Mikulicic 0:c0ecb8bf28eb 16150 if (opts.object_arena_size == 0) opts.object_arena_size = 200;
Marko Mikulicic 0:c0ecb8bf28eb 16151 if (opts.function_arena_size == 0) opts.function_arena_size = 100;
Marko Mikulicic 0:c0ecb8bf28eb 16152 if (opts.property_arena_size == 0) opts.property_arena_size = 400;
Marko Mikulicic 0:c0ecb8bf28eb 16153
Marko Mikulicic 0:c0ecb8bf28eb 16154 if ((v7 = (struct v7 *) calloc(1, sizeof(*v7))) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16155 #ifdef V7_STACK_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 16156 v7->sp_limit = (void *) ((uintptr_t) opts.c_stack_base - (V7_STACK_SIZE));
Marko Mikulicic 0:c0ecb8bf28eb 16157 v7->sp_lwm = opts.c_stack_base;
Marko Mikulicic 0:c0ecb8bf28eb 16158 #ifdef V7_STACK_GUARD_MIN_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 16159 v7_sp_limit = v7->sp_limit;
Marko Mikulicic 0:c0ecb8bf28eb 16160 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16161 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16162
Marko Mikulicic 0:c0ecb8bf28eb 16163 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 16164 v7->next_v7 = v7_head;
Marko Mikulicic 0:c0ecb8bf28eb 16165 v7_head = v7;
Marko Mikulicic 0:c0ecb8bf28eb 16166 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16167
Marko Mikulicic 0:c0ecb8bf28eb 16168 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 16169 v7->gc_next_asn = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16170 v7->gc_min_asn = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16171 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16172
Marko Mikulicic 0:c0ecb8bf28eb 16173 v7->cur_dense_prop =
Marko Mikulicic 0:c0ecb8bf28eb 16174 (struct v7_property *) calloc(1, sizeof(struct v7_property));
Marko Mikulicic 0:c0ecb8bf28eb 16175 gc_arena_init(&v7->generic_object_arena, sizeof(struct v7_generic_object),
Marko Mikulicic 0:c0ecb8bf28eb 16176 opts.object_arena_size, 10, "object");
Marko Mikulicic 0:c0ecb8bf28eb 16177 v7->generic_object_arena.destructor = generic_object_destructor;
Marko Mikulicic 0:c0ecb8bf28eb 16178 gc_arena_init(&v7->function_arena, sizeof(struct v7_js_function),
Marko Mikulicic 0:c0ecb8bf28eb 16179 opts.function_arena_size, 10, "function");
Marko Mikulicic 0:c0ecb8bf28eb 16180 v7->function_arena.destructor = function_destructor;
Marko Mikulicic 0:c0ecb8bf28eb 16181 gc_arena_init(&v7->property_arena, sizeof(struct v7_property),
Marko Mikulicic 0:c0ecb8bf28eb 16182 opts.property_arena_size, 10, "property");
Marko Mikulicic 0:c0ecb8bf28eb 16183 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16184 v7->property_arena.destructor = property_destructor;
Marko Mikulicic 0:c0ecb8bf28eb 16185 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16186
Marko Mikulicic 0:c0ecb8bf28eb 16187 /*
Marko Mikulicic 0:c0ecb8bf28eb 16188 * The compacting GC exploits the null terminator of the previous
Marko Mikulicic 0:c0ecb8bf28eb 16189 * string as marker.
Marko Mikulicic 0:c0ecb8bf28eb 16190 */
Marko Mikulicic 0:c0ecb8bf28eb 16191 mbuf_append(&v7->owned_strings, &z, 1);
Marko Mikulicic 0:c0ecb8bf28eb 16192
Marko Mikulicic 0:c0ecb8bf28eb 16193 v7->inhibit_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16194 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16195
Marko Mikulicic 0:c0ecb8bf28eb 16196 v7->call_stack = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16197 v7->bottom_call_frame = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16198
Marko Mikulicic 0:c0ecb8bf28eb 16199 #if defined(V7_THAW) && !defined(V7_FREEZE_NOT_READONLY)
Marko Mikulicic 0:c0ecb8bf28eb 16200 {
Marko Mikulicic 0:c0ecb8bf28eb 16201 struct v7_generic_object *obj;
Marko Mikulicic 0:c0ecb8bf28eb 16202 v7->vals = *fr_vals;
Marko Mikulicic 0:c0ecb8bf28eb 16203 v7->vals.global_object = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16204
Marko Mikulicic 0:c0ecb8bf28eb 16205 /*
Marko Mikulicic 0:c0ecb8bf28eb 16206 * The global object has to be mutable.
Marko Mikulicic 0:c0ecb8bf28eb 16207 */
Marko Mikulicic 0:c0ecb8bf28eb 16208 obj = get_generic_object_struct(v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 16209 *obj = *get_generic_object_struct(fr_vals->global_object);
Marko Mikulicic 0:c0ecb8bf28eb 16210 obj->base.attributes &= ~(V7_OBJ_NOT_EXTENSIBLE | V7_OBJ_OFF_HEAP);
Marko Mikulicic 0:c0ecb8bf28eb 16211 v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 16212 }
Marko Mikulicic 0:c0ecb8bf28eb 16213 #else
Marko Mikulicic 0:c0ecb8bf28eb 16214 init_stdlib(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16215 init_file(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16216 init_crypto(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16217 init_socket(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16218 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16219
Marko Mikulicic 0:c0ecb8bf28eb 16220 v7->inhibit_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16221 }
Marko Mikulicic 0:c0ecb8bf28eb 16222
Marko Mikulicic 0:c0ecb8bf28eb 16223 return v7;
Marko Mikulicic 0:c0ecb8bf28eb 16224 }
Marko Mikulicic 0:c0ecb8bf28eb 16225
Marko Mikulicic 0:c0ecb8bf28eb 16226 val_t v7_get_global(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16227 return v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 16228 }
Marko Mikulicic 0:c0ecb8bf28eb 16229
Marko Mikulicic 0:c0ecb8bf28eb 16230 void v7_destroy(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16231 if (v7 == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 16232 gc_arena_destroy(v7, &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 16233 gc_arena_destroy(v7, &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 16234 gc_arena_destroy(v7, &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 16235
Marko Mikulicic 0:c0ecb8bf28eb 16236 mbuf_free(&v7->owned_strings);
Marko Mikulicic 0:c0ecb8bf28eb 16237 mbuf_free(&v7->owned_values);
Marko Mikulicic 0:c0ecb8bf28eb 16238 mbuf_free(&v7->foreign_strings);
Marko Mikulicic 0:c0ecb8bf28eb 16239 mbuf_free(&v7->json_visited_stack);
Marko Mikulicic 0:c0ecb8bf28eb 16240 mbuf_free(&v7->tmp_stack);
Marko Mikulicic 0:c0ecb8bf28eb 16241 mbuf_free(&v7->act_bcodes);
Marko Mikulicic 0:c0ecb8bf28eb 16242 mbuf_free(&v7->stack);
Marko Mikulicic 0:c0ecb8bf28eb 16243
Marko Mikulicic 0:c0ecb8bf28eb 16244 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 16245 /* delete this v7 */
Marko Mikulicic 0:c0ecb8bf28eb 16246 {
Marko Mikulicic 0:c0ecb8bf28eb 16247 struct v7 *v, **prevp = &v7_head;
Marko Mikulicic 0:c0ecb8bf28eb 16248 for (v = v7_head; v != NULL; prevp = &v->next_v7, v = v->next_v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16249 if (v == v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16250 *prevp = v->next_v7;
Marko Mikulicic 0:c0ecb8bf28eb 16251 break;
Marko Mikulicic 0:c0ecb8bf28eb 16252 }
Marko Mikulicic 0:c0ecb8bf28eb 16253 }
Marko Mikulicic 0:c0ecb8bf28eb 16254 }
Marko Mikulicic 0:c0ecb8bf28eb 16255 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16256
Marko Mikulicic 0:c0ecb8bf28eb 16257 free(v7->cur_dense_prop);
Marko Mikulicic 0:c0ecb8bf28eb 16258 free(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16259 }
Marko Mikulicic 0:c0ecb8bf28eb 16260
Marko Mikulicic 0:c0ecb8bf28eb 16261 v7_val_t v7_get_this(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16262 /*
Marko Mikulicic 0:c0ecb8bf28eb 16263 * By default, when there's no active call frame, will return Global Object
Marko Mikulicic 0:c0ecb8bf28eb 16264 */
Marko Mikulicic 0:c0ecb8bf28eb 16265 v7_val_t ret = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 16266
Marko Mikulicic 0:c0ecb8bf28eb 16267 struct v7_call_frame_base *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 16268 find_call_frame(v7, V7_CALL_FRAME_MASK_BCODE | V7_CALL_FRAME_MASK_CFUNC);
Marko Mikulicic 0:c0ecb8bf28eb 16269
Marko Mikulicic 0:c0ecb8bf28eb 16270 if (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16271 if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 16272 ret = ((struct v7_call_frame_bcode *) call_frame)->vals.this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 16273 } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 16274 ret = ((struct v7_call_frame_cfunc *) call_frame)->vals.this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 16275 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16276 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 16277 }
Marko Mikulicic 0:c0ecb8bf28eb 16278 }
Marko Mikulicic 0:c0ecb8bf28eb 16279
Marko Mikulicic 0:c0ecb8bf28eb 16280 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16281 }
Marko Mikulicic 0:c0ecb8bf28eb 16282
Marko Mikulicic 0:c0ecb8bf28eb 16283 V7_PRIVATE v7_val_t get_scope(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16284 struct v7_call_frame_private *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 16285 (struct v7_call_frame_private *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 16286 v7, V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 16287
Marko Mikulicic 0:c0ecb8bf28eb 16288 if (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16289 return call_frame->vals.scope;
Marko Mikulicic 0:c0ecb8bf28eb 16290 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16291 /* No active call frame, return global object */
Marko Mikulicic 0:c0ecb8bf28eb 16292 return v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 16293 }
Marko Mikulicic 0:c0ecb8bf28eb 16294 }
Marko Mikulicic 0:c0ecb8bf28eb 16295
Marko Mikulicic 0:c0ecb8bf28eb 16296 V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16297 struct v7_call_frame_bcode *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 16298 (struct v7_call_frame_bcode *) find_call_frame(v7,
Marko Mikulicic 0:c0ecb8bf28eb 16299 V7_CALL_FRAME_MASK_BCODE);
Marko Mikulicic 0:c0ecb8bf28eb 16300
Marko Mikulicic 0:c0ecb8bf28eb 16301 if (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16302 return call_frame->bcode->strict_mode;
Marko Mikulicic 0:c0ecb8bf28eb 16303 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16304 /* No active call frame, assume no strict mode */
Marko Mikulicic 0:c0ecb8bf28eb 16305 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 16306 }
Marko Mikulicic 0:c0ecb8bf28eb 16307 }
Marko Mikulicic 0:c0ecb8bf28eb 16308
Marko Mikulicic 0:c0ecb8bf28eb 16309 v7_val_t v7_get_arguments(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16310 return v7->vals.arguments;
Marko Mikulicic 0:c0ecb8bf28eb 16311 }
Marko Mikulicic 0:c0ecb8bf28eb 16312
Marko Mikulicic 0:c0ecb8bf28eb 16313 v7_val_t v7_arg(struct v7 *v7, unsigned long n) {
Marko Mikulicic 0:c0ecb8bf28eb 16314 return v7_array_get(v7, v7->vals.arguments, n);
Marko Mikulicic 0:c0ecb8bf28eb 16315 }
Marko Mikulicic 0:c0ecb8bf28eb 16316
Marko Mikulicic 0:c0ecb8bf28eb 16317 unsigned long v7_argc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16318 return v7_array_length(v7, v7->vals.arguments);
Marko Mikulicic 0:c0ecb8bf28eb 16319 }
Marko Mikulicic 0:c0ecb8bf28eb 16320
Marko Mikulicic 0:c0ecb8bf28eb 16321 void v7_own(struct v7 *v7, v7_val_t *v) {
Marko Mikulicic 0:c0ecb8bf28eb 16322 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 16323 mbuf_append(&v7->owned_values, &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 16324 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 16325 }
Marko Mikulicic 0:c0ecb8bf28eb 16326
Marko Mikulicic 0:c0ecb8bf28eb 16327 int v7_disown(struct v7 *v7, v7_val_t *v) {
Marko Mikulicic 0:c0ecb8bf28eb 16328 v7_val_t **vp =
Marko Mikulicic 0:c0ecb8bf28eb 16329 (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 16330
Marko Mikulicic 0:c0ecb8bf28eb 16331 for (; (char *) vp >= v7->owned_values.buf; vp--) {
Marko Mikulicic 0:c0ecb8bf28eb 16332 if (*vp == v) {
Marko Mikulicic 0:c0ecb8bf28eb 16333 *vp = *(v7_val_t **) (v7->owned_values.buf + v7->owned_values.len -
Marko Mikulicic 0:c0ecb8bf28eb 16334 sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 16335 v7->owned_values.len -= sizeof(v);
Marko Mikulicic 0:c0ecb8bf28eb 16336 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 16337 }
Marko Mikulicic 0:c0ecb8bf28eb 16338 }
Marko Mikulicic 0:c0ecb8bf28eb 16339
Marko Mikulicic 0:c0ecb8bf28eb 16340 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 16341 }
Marko Mikulicic 0:c0ecb8bf28eb 16342
Marko Mikulicic 0:c0ecb8bf28eb 16343 void v7_set_gc_enabled(struct v7 *v7, int enabled) {
Marko Mikulicic 0:c0ecb8bf28eb 16344 v7->inhibit_gc = !enabled;
Marko Mikulicic 0:c0ecb8bf28eb 16345 }
Marko Mikulicic 0:c0ecb8bf28eb 16346
Marko Mikulicic 0:c0ecb8bf28eb 16347 void v7_interrupt(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16348 v7->interrupted = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16349 }
Marko Mikulicic 0:c0ecb8bf28eb 16350
Marko Mikulicic 0:c0ecb8bf28eb 16351 const char *v7_get_parser_error(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16352 return v7->error_msg;
Marko Mikulicic 0:c0ecb8bf28eb 16353 }
Marko Mikulicic 0:c0ecb8bf28eb 16354
Marko Mikulicic 0:c0ecb8bf28eb 16355 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 16356
Marko Mikulicic 0:c0ecb8bf28eb 16357 int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what) {
Marko Mikulicic 0:c0ecb8bf28eb 16358 assert(what < V7_STACK_STATS_CNT);
Marko Mikulicic 0:c0ecb8bf28eb 16359 return v7->stack_stat[what];
Marko Mikulicic 0:c0ecb8bf28eb 16360 }
Marko Mikulicic 0:c0ecb8bf28eb 16361
Marko Mikulicic 0:c0ecb8bf28eb 16362 void v7_stack_stat_clean(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16363 memset(v7->stack_stat, 0x00, sizeof(v7->stack_stat));
Marko Mikulicic 0:c0ecb8bf28eb 16364 }
Marko Mikulicic 0:c0ecb8bf28eb 16365
Marko Mikulicic 0:c0ecb8bf28eb 16366 #endif /* V7_ENABLE_STACK_TRACKING */
Marko Mikulicic 0:c0ecb8bf28eb 16367 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16368 #line 1 "v7/src/primitive.c"
Marko Mikulicic 0:c0ecb8bf28eb 16369 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16370 /*
Marko Mikulicic 0:c0ecb8bf28eb 16371 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16372 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16373 */
Marko Mikulicic 0:c0ecb8bf28eb 16374
Marko Mikulicic 0:c0ecb8bf28eb 16375 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16376 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16377 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16378
Marko Mikulicic 0:c0ecb8bf28eb 16379 /* Number {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16380
Marko Mikulicic 0:c0ecb8bf28eb 16381 NOINSTR static v7_val_t mk_number(double v) {
Marko Mikulicic 0:c0ecb8bf28eb 16382 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 16383 /* not every NaN is a JS NaN */
Marko Mikulicic 0:c0ecb8bf28eb 16384 if (isnan(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16385 res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 16386 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16387 union {
Marko Mikulicic 0:c0ecb8bf28eb 16388 double d;
Marko Mikulicic 0:c0ecb8bf28eb 16389 val_t r;
Marko Mikulicic 0:c0ecb8bf28eb 16390 } u;
Marko Mikulicic 0:c0ecb8bf28eb 16391 u.d = v;
Marko Mikulicic 0:c0ecb8bf28eb 16392 res = u.r;
Marko Mikulicic 0:c0ecb8bf28eb 16393 }
Marko Mikulicic 0:c0ecb8bf28eb 16394 return res;
Marko Mikulicic 0:c0ecb8bf28eb 16395 }
Marko Mikulicic 0:c0ecb8bf28eb 16396
Marko Mikulicic 0:c0ecb8bf28eb 16397 NOINSTR static double get_double(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16398 union {
Marko Mikulicic 0:c0ecb8bf28eb 16399 double d;
Marko Mikulicic 0:c0ecb8bf28eb 16400 val_t v;
Marko Mikulicic 0:c0ecb8bf28eb 16401 } u;
Marko Mikulicic 0:c0ecb8bf28eb 16402 u.v = v;
Marko Mikulicic 0:c0ecb8bf28eb 16403 /* Due to NaN packing, any non-numeric value is already a valid NaN value */
Marko Mikulicic 0:c0ecb8bf28eb 16404 return u.d;
Marko Mikulicic 0:c0ecb8bf28eb 16405 }
Marko Mikulicic 0:c0ecb8bf28eb 16406
Marko Mikulicic 0:c0ecb8bf28eb 16407 NOINSTR static v7_val_t mk_boolean(int v) {
Marko Mikulicic 0:c0ecb8bf28eb 16408 return (!!v) | V7_TAG_BOOLEAN;
Marko Mikulicic 0:c0ecb8bf28eb 16409 }
Marko Mikulicic 0:c0ecb8bf28eb 16410
Marko Mikulicic 0:c0ecb8bf28eb 16411 NOINSTR static int get_bool(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16412 if (v7_is_boolean(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16413 return v & 1;
Marko Mikulicic 0:c0ecb8bf28eb 16414 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16415 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 16416 }
Marko Mikulicic 0:c0ecb8bf28eb 16417 }
Marko Mikulicic 0:c0ecb8bf28eb 16418
Marko Mikulicic 0:c0ecb8bf28eb 16419 NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double v) {
Marko Mikulicic 0:c0ecb8bf28eb 16420 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16421 return mk_number(v);
Marko Mikulicic 0:c0ecb8bf28eb 16422 }
Marko Mikulicic 0:c0ecb8bf28eb 16423
Marko Mikulicic 0:c0ecb8bf28eb 16424 NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16425 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16426 return get_double(v);
Marko Mikulicic 0:c0ecb8bf28eb 16427 }
Marko Mikulicic 0:c0ecb8bf28eb 16428
Marko Mikulicic 0:c0ecb8bf28eb 16429 NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16430 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16431 return (int) get_double(v);
Marko Mikulicic 0:c0ecb8bf28eb 16432 }
Marko Mikulicic 0:c0ecb8bf28eb 16433
Marko Mikulicic 0:c0ecb8bf28eb 16434 int v7_is_number(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16435 return v == V7_TAG_NAN || !isnan(get_double(v));
Marko Mikulicic 0:c0ecb8bf28eb 16436 }
Marko Mikulicic 0:c0ecb8bf28eb 16437
Marko Mikulicic 0:c0ecb8bf28eb 16438 V7_PRIVATE int is_finite(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16439 return v7_is_number(v) && v != V7_TAG_NAN && !isinf(v7_get_double(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 16440 }
Marko Mikulicic 0:c0ecb8bf28eb 16441
Marko Mikulicic 0:c0ecb8bf28eb 16442 /* }}} Number */
Marko Mikulicic 0:c0ecb8bf28eb 16443
Marko Mikulicic 0:c0ecb8bf28eb 16444 /* Boolean {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16445
Marko Mikulicic 0:c0ecb8bf28eb 16446 NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int v) {
Marko Mikulicic 0:c0ecb8bf28eb 16447 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16448 return mk_boolean(v);
Marko Mikulicic 0:c0ecb8bf28eb 16449 }
Marko Mikulicic 0:c0ecb8bf28eb 16450
Marko Mikulicic 0:c0ecb8bf28eb 16451 NOINSTR int v7_get_bool(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16452 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16453 return get_bool(v);
Marko Mikulicic 0:c0ecb8bf28eb 16454 }
Marko Mikulicic 0:c0ecb8bf28eb 16455
Marko Mikulicic 0:c0ecb8bf28eb 16456 int v7_is_boolean(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16457 return (v & V7_TAG_MASK) == V7_TAG_BOOLEAN;
Marko Mikulicic 0:c0ecb8bf28eb 16458 }
Marko Mikulicic 0:c0ecb8bf28eb 16459
Marko Mikulicic 0:c0ecb8bf28eb 16460 /* }}} Boolean */
Marko Mikulicic 0:c0ecb8bf28eb 16461
Marko Mikulicic 0:c0ecb8bf28eb 16462 /* null {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16463
Marko Mikulicic 0:c0ecb8bf28eb 16464 NOINSTR v7_val_t v7_mk_null(void) {
Marko Mikulicic 0:c0ecb8bf28eb 16465 return V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16466 }
Marko Mikulicic 0:c0ecb8bf28eb 16467
Marko Mikulicic 0:c0ecb8bf28eb 16468 int v7_is_null(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16469 return v == V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16470 }
Marko Mikulicic 0:c0ecb8bf28eb 16471
Marko Mikulicic 0:c0ecb8bf28eb 16472 /* }}} null */
Marko Mikulicic 0:c0ecb8bf28eb 16473
Marko Mikulicic 0:c0ecb8bf28eb 16474 /* undefined {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16475
Marko Mikulicic 0:c0ecb8bf28eb 16476 NOINSTR v7_val_t v7_mk_undefined(void) {
Marko Mikulicic 0:c0ecb8bf28eb 16477 return V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16478 }
Marko Mikulicic 0:c0ecb8bf28eb 16479
Marko Mikulicic 0:c0ecb8bf28eb 16480 int v7_is_undefined(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16481 return v == V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16482 }
Marko Mikulicic 0:c0ecb8bf28eb 16483
Marko Mikulicic 0:c0ecb8bf28eb 16484 /* }}} undefined */
Marko Mikulicic 0:c0ecb8bf28eb 16485
Marko Mikulicic 0:c0ecb8bf28eb 16486 /* Foreign {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16487
Marko Mikulicic 0:c0ecb8bf28eb 16488 V7_PRIVATE val_t pointer_to_value(void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 16489 uint64_t n = ((uint64_t)(uintptr_t) p);
Marko Mikulicic 0:c0ecb8bf28eb 16490
Marko Mikulicic 0:c0ecb8bf28eb 16491 assert((n & V7_TAG_MASK) == 0 || (n & V7_TAG_MASK) == (~0 & V7_TAG_MASK));
Marko Mikulicic 0:c0ecb8bf28eb 16492 return n & ~V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 16493 }
Marko Mikulicic 0:c0ecb8bf28eb 16494
Marko Mikulicic 0:c0ecb8bf28eb 16495 V7_PRIVATE void *get_ptr(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16496 return (void *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL);
Marko Mikulicic 0:c0ecb8bf28eb 16497 }
Marko Mikulicic 0:c0ecb8bf28eb 16498
Marko Mikulicic 0:c0ecb8bf28eb 16499 NOINSTR void *v7_get_ptr(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16500 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16501 if (!v7_is_foreign(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16502 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16503 }
Marko Mikulicic 0:c0ecb8bf28eb 16504 return get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 16505 }
Marko Mikulicic 0:c0ecb8bf28eb 16506
Marko Mikulicic 0:c0ecb8bf28eb 16507 NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 16508 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16509 return pointer_to_value(p) | V7_TAG_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 16510 }
Marko Mikulicic 0:c0ecb8bf28eb 16511
Marko Mikulicic 0:c0ecb8bf28eb 16512 int v7_is_foreign(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16513 return (v & V7_TAG_MASK) == V7_TAG_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 16514 }
Marko Mikulicic 0:c0ecb8bf28eb 16515
Marko Mikulicic 0:c0ecb8bf28eb 16516 /* }}} Foreign */
Marko Mikulicic 0:c0ecb8bf28eb 16517 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16518 #line 1 "v7/src/function.c"
Marko Mikulicic 0:c0ecb8bf28eb 16519 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16520 /*
Marko Mikulicic 0:c0ecb8bf28eb 16521 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16522 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16523 */
Marko Mikulicic 0:c0ecb8bf28eb 16524
Marko Mikulicic 0:c0ecb8bf28eb 16525 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16526 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16527 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16528 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16529 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16530 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16531
Marko Mikulicic 0:c0ecb8bf28eb 16532 static val_t js_function_to_value(struct v7_js_function *o) {
Marko Mikulicic 0:c0ecb8bf28eb 16533 return pointer_to_value(o) | V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16534 }
Marko Mikulicic 0:c0ecb8bf28eb 16535
Marko Mikulicic 0:c0ecb8bf28eb 16536 V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16537 struct v7_js_function *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16538 assert(is_js_function(v));
Marko Mikulicic 0:c0ecb8bf28eb 16539 ret = (struct v7_js_function *) get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 16540 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16541 if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_JS_FUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 16542 fprintf(stderr, "entity_id: not a function!\n");
Marko Mikulicic 0:c0ecb8bf28eb 16543 abort();
Marko Mikulicic 0:c0ecb8bf28eb 16544 } else if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 16545 fprintf(stderr, "entity_id: not an object!\n");
Marko Mikulicic 0:c0ecb8bf28eb 16546 abort();
Marko Mikulicic 0:c0ecb8bf28eb 16547 }
Marko Mikulicic 0:c0ecb8bf28eb 16548 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16549 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16550 }
Marko Mikulicic 0:c0ecb8bf28eb 16551
Marko Mikulicic 0:c0ecb8bf28eb 16552 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 16553 val_t mk_js_function(struct v7 *v7, struct v7_generic_object *scope,
Marko Mikulicic 0:c0ecb8bf28eb 16554 val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 16555 struct v7_js_function *f;
Marko Mikulicic 0:c0ecb8bf28eb 16556 val_t fval = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16557 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16558 tmp_stack_push(&tf, &proto);
Marko Mikulicic 0:c0ecb8bf28eb 16559 tmp_stack_push(&tf, &fval);
Marko Mikulicic 0:c0ecb8bf28eb 16560
Marko Mikulicic 0:c0ecb8bf28eb 16561 f = new_function(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16562
Marko Mikulicic 0:c0ecb8bf28eb 16563 if (f == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16564 /* fval is left `null` */
Marko Mikulicic 0:c0ecb8bf28eb 16565 goto cleanup;
Marko Mikulicic 0:c0ecb8bf28eb 16566 }
Marko Mikulicic 0:c0ecb8bf28eb 16567
Marko Mikulicic 0:c0ecb8bf28eb 16568 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16569 f->base.entity_id_base = V7_ENTITY_ID_PART_OBJ;
Marko Mikulicic 0:c0ecb8bf28eb 16570 f->base.entity_id_spec = V7_ENTITY_ID_PART_JS_FUNC;
Marko Mikulicic 0:c0ecb8bf28eb 16571 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16572
Marko Mikulicic 0:c0ecb8bf28eb 16573 fval = js_function_to_value(f);
Marko Mikulicic 0:c0ecb8bf28eb 16574
Marko Mikulicic 0:c0ecb8bf28eb 16575 f->base.properties = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16576 f->scope = scope;
Marko Mikulicic 0:c0ecb8bf28eb 16577
Marko Mikulicic 0:c0ecb8bf28eb 16578 /*
Marko Mikulicic 0:c0ecb8bf28eb 16579 * Before setting a `V7_OBJ_FUNCTION` flag, make sure we don't have
Marko Mikulicic 0:c0ecb8bf28eb 16580 * `V7_OBJ_DENSE_ARRAY` flag set
Marko Mikulicic 0:c0ecb8bf28eb 16581 */
Marko Mikulicic 0:c0ecb8bf28eb 16582 assert(!(f->base.attributes & V7_OBJ_DENSE_ARRAY));
Marko Mikulicic 0:c0ecb8bf28eb 16583 f->base.attributes |= V7_OBJ_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16584
Marko Mikulicic 0:c0ecb8bf28eb 16585 /* TODO(mkm): lazily create these properties on first access */
Marko Mikulicic 0:c0ecb8bf28eb 16586 if (v7_is_object(proto)) {
Marko Mikulicic 0:c0ecb8bf28eb 16587 v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), fval);
Marko Mikulicic 0:c0ecb8bf28eb 16588 v7_def(v7, fval, "prototype", 9,
Marko Mikulicic 0:c0ecb8bf28eb 16589 V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0), proto);
Marko Mikulicic 0:c0ecb8bf28eb 16590 }
Marko Mikulicic 0:c0ecb8bf28eb 16591
Marko Mikulicic 0:c0ecb8bf28eb 16592 cleanup:
Marko Mikulicic 0:c0ecb8bf28eb 16593 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 16594 return fval;
Marko Mikulicic 0:c0ecb8bf28eb 16595 }
Marko Mikulicic 0:c0ecb8bf28eb 16596
Marko Mikulicic 0:c0ecb8bf28eb 16597 V7_PRIVATE int is_js_function(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16598 return (v & V7_TAG_MASK) == V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16599 }
Marko Mikulicic 0:c0ecb8bf28eb 16600
Marko Mikulicic 0:c0ecb8bf28eb 16601 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 16602 v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *f, int num_args) {
Marko Mikulicic 0:c0ecb8bf28eb 16603 val_t obj = mk_object(v7, v7->vals.function_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 16604 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16605 tmp_stack_push(&tf, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 16606 v7_def(v7, obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_cfunction(f));
Marko Mikulicic 0:c0ecb8bf28eb 16607 if (num_args >= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 16608 v7_def(v7, obj, "length", 6, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
Marko Mikulicic 0:c0ecb8bf28eb 16609 V7_DESC_CONFIGURABLE(0)),
Marko Mikulicic 0:c0ecb8bf28eb 16610 v7_mk_number(v7, num_args));
Marko Mikulicic 0:c0ecb8bf28eb 16611 }
Marko Mikulicic 0:c0ecb8bf28eb 16612 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 16613 return obj;
Marko Mikulicic 0:c0ecb8bf28eb 16614 }
Marko Mikulicic 0:c0ecb8bf28eb 16615
Marko Mikulicic 0:c0ecb8bf28eb 16616 V7_PRIVATE v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 16617 v7_cfunction_t *f, int num_args,
Marko Mikulicic 0:c0ecb8bf28eb 16618 v7_val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 16619 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16620 v7_val_t res = mk_cfunction_obj(v7, f, num_args);
Marko Mikulicic 0:c0ecb8bf28eb 16621
Marko Mikulicic 0:c0ecb8bf28eb 16622 tmp_stack_push(&tf, &res);
Marko Mikulicic 0:c0ecb8bf28eb 16623
Marko Mikulicic 0:c0ecb8bf28eb 16624 v7_def(v7, res, "prototype", 9, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
Marko Mikulicic 0:c0ecb8bf28eb 16625 V7_DESC_CONFIGURABLE(0)),
Marko Mikulicic 0:c0ecb8bf28eb 16626 proto);
Marko Mikulicic 0:c0ecb8bf28eb 16627 v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), res);
Marko Mikulicic 0:c0ecb8bf28eb 16628 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 16629 return res;
Marko Mikulicic 0:c0ecb8bf28eb 16630 }
Marko Mikulicic 0:c0ecb8bf28eb 16631
Marko Mikulicic 0:c0ecb8bf28eb 16632 V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 16633 union {
Marko Mikulicic 0:c0ecb8bf28eb 16634 void *p;
Marko Mikulicic 0:c0ecb8bf28eb 16635 v7_cfunction_t *f;
Marko Mikulicic 0:c0ecb8bf28eb 16636 } u;
Marko Mikulicic 0:c0ecb8bf28eb 16637 u.f = f;
Marko Mikulicic 0:c0ecb8bf28eb 16638 return pointer_to_value(u.p) | V7_TAG_CFUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16639 }
Marko Mikulicic 0:c0ecb8bf28eb 16640
Marko Mikulicic 0:c0ecb8bf28eb 16641 V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16642 v7_cfunction_t *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16643
Marko Mikulicic 0:c0ecb8bf28eb 16644 if (is_cfunction_lite(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16645 /* Implementation is identical to get_ptr but is separate since
Marko Mikulicic 0:c0ecb8bf28eb 16646 * object pointers are not directly convertible to function pointers
Marko Mikulicic 0:c0ecb8bf28eb 16647 * according to ISO C and generates a warning in -Wpedantic mode. */
Marko Mikulicic 0:c0ecb8bf28eb 16648 ret = (v7_cfunction_t *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL);
Marko Mikulicic 0:c0ecb8bf28eb 16649 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16650 /* maybe cfunction object */
Marko Mikulicic 0:c0ecb8bf28eb 16651
Marko Mikulicic 0:c0ecb8bf28eb 16652 /* extract the hidden property from a cfunction_object */
Marko Mikulicic 0:c0ecb8bf28eb 16653 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16654 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 16655 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16656 /* yes, it's cfunction object. Extract cfunction pointer from it */
Marko Mikulicic 0:c0ecb8bf28eb 16657 ret = get_cfunction_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 16658 }
Marko Mikulicic 0:c0ecb8bf28eb 16659 }
Marko Mikulicic 0:c0ecb8bf28eb 16660
Marko Mikulicic 0:c0ecb8bf28eb 16661 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16662 }
Marko Mikulicic 0:c0ecb8bf28eb 16663
Marko Mikulicic 0:c0ecb8bf28eb 16664 V7_PRIVATE int is_cfunction_lite(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16665 return (v & V7_TAG_MASK) == V7_TAG_CFUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16666 }
Marko Mikulicic 0:c0ecb8bf28eb 16667
Marko Mikulicic 0:c0ecb8bf28eb 16668 V7_PRIVATE int is_cfunction_obj(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16669 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16670 if (v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16671 /* extract the hidden property from a cfunction_object */
Marko Mikulicic 0:c0ecb8bf28eb 16672 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16673 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 16674 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16675 v = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 16676 }
Marko Mikulicic 0:c0ecb8bf28eb 16677
Marko Mikulicic 0:c0ecb8bf28eb 16678 ret = is_cfunction_lite(v);
Marko Mikulicic 0:c0ecb8bf28eb 16679 }
Marko Mikulicic 0:c0ecb8bf28eb 16680 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16681 }
Marko Mikulicic 0:c0ecb8bf28eb 16682
Marko Mikulicic 0:c0ecb8bf28eb 16683 v7_val_t v7_mk_function(struct v7 *v7, v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 16684 return mk_cfunction_obj(v7, f, -1);
Marko Mikulicic 0:c0ecb8bf28eb 16685 }
Marko Mikulicic 0:c0ecb8bf28eb 16686
Marko Mikulicic 0:c0ecb8bf28eb 16687 v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f,
Marko Mikulicic 0:c0ecb8bf28eb 16688 v7_val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 16689 return mk_cfunction_obj_with_proto(v7, f, ~0, proto);
Marko Mikulicic 0:c0ecb8bf28eb 16690 }
Marko Mikulicic 0:c0ecb8bf28eb 16691
Marko Mikulicic 0:c0ecb8bf28eb 16692 v7_val_t v7_mk_cfunction(v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 16693 return mk_cfunction_lite(f);
Marko Mikulicic 0:c0ecb8bf28eb 16694 }
Marko Mikulicic 0:c0ecb8bf28eb 16695
Marko Mikulicic 0:c0ecb8bf28eb 16696 int v7_is_callable(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16697 return is_js_function(v) || is_cfunction_lite(v) || is_cfunction_obj(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16698 }
Marko Mikulicic 0:c0ecb8bf28eb 16699 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16700 #line 1 "v7/src/exec.c"
Marko Mikulicic 0:c0ecb8bf28eb 16701 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16702 /*
Marko Mikulicic 0:c0ecb8bf28eb 16703 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16704 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16705 */
Marko Mikulicic 0:c0ecb8bf28eb 16706
Marko Mikulicic 0:c0ecb8bf28eb 16707 /* osdep.h must be included before `cs_file.h` TODO(dfrank) : fix this */
Marko Mikulicic 0:c0ecb8bf28eb 16708 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16709 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16710 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16711 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16712 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16713 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16714 /* Amalgamated: #include "v7/src/compiler.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16715 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16716
Marko Mikulicic 0:c0ecb8bf28eb 16717 enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16718 return b_exec(v7, js_code, strlen(js_code), NULL, V7_UNDEFINED, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16719 V7_UNDEFINED, 0, 0, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16720 }
Marko Mikulicic 0:c0ecb8bf28eb 16721
Marko Mikulicic 0:c0ecb8bf28eb 16722 enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code,
Marko Mikulicic 0:c0ecb8bf28eb 16723 const struct v7_exec_opts *opts, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16724 return b_exec(v7, js_code, strlen(js_code), opts->filename, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16725 V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16726 (opts->this_obj == 0 ? V7_UNDEFINED : opts->this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 16727 opts->is_json, 0, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16728 }
Marko Mikulicic 0:c0ecb8bf28eb 16729
Marko Mikulicic 0:c0ecb8bf28eb 16730 enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16731 return b_exec(v7, str, strlen(str), NULL, V7_UNDEFINED, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16732 V7_UNDEFINED, 1, 0, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16733 }
Marko Mikulicic 0:c0ecb8bf28eb 16734
Marko Mikulicic 0:c0ecb8bf28eb 16735 #ifndef V7_NO_FS
Marko Mikulicic 0:c0ecb8bf28eb 16736 static enum v7_err exec_file(struct v7 *v7, const char *path, val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 16737 int is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 16738 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 16739 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 16740 size_t file_size;
Marko Mikulicic 0:c0ecb8bf28eb 16741 char *(*rd)(const char *, size_t *);
Marko Mikulicic 0:c0ecb8bf28eb 16742
Marko Mikulicic 0:c0ecb8bf28eb 16743 rd = cs_read_file;
Marko Mikulicic 0:c0ecb8bf28eb 16744 #ifdef V7_MMAP_EXEC
Marko Mikulicic 0:c0ecb8bf28eb 16745 rd = cs_mmap_file;
Marko Mikulicic 0:c0ecb8bf28eb 16746 #ifdef V7_MMAP_EXEC_ONLY
Marko Mikulicic 0:c0ecb8bf28eb 16747 #define I_STRINGIFY(x) #x
Marko Mikulicic 0:c0ecb8bf28eb 16748 #define I_STRINGIFY2(x) I_STRINGIFY(x)
Marko Mikulicic 0:c0ecb8bf28eb 16749
Marko Mikulicic 0:c0ecb8bf28eb 16750 /* use mmap only for .js files */
Marko Mikulicic 0:c0ecb8bf28eb 16751 if (strlen(path) <= 3 || strcmp(path + strlen(path) - 3, ".js") != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 16752 rd = cs_read_file;
Marko Mikulicic 0:c0ecb8bf28eb 16753 }
Marko Mikulicic 0:c0ecb8bf28eb 16754 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16755 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16756
Marko Mikulicic 0:c0ecb8bf28eb 16757 if ((p = rd(path, &file_size)) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16758 rcode = v7_throwf(v7, SYNTAX_ERROR, "cannot open [%s]", path);
Marko Mikulicic 0:c0ecb8bf28eb 16759 /*
Marko Mikulicic 0:c0ecb8bf28eb 16760 * In order to maintain compat with existing API, we should save the
Marko Mikulicic 0:c0ecb8bf28eb 16761 * current exception value into `*res`
Marko Mikulicic 0:c0ecb8bf28eb 16762 *
Marko Mikulicic 0:c0ecb8bf28eb 16763 * TODO(dfrank): probably change API: clients can use
Marko Mikulicic 0:c0ecb8bf28eb 16764 *`v7_get_thrown_value()` now.
Marko Mikulicic 0:c0ecb8bf28eb 16765 */
Marko Mikulicic 0:c0ecb8bf28eb 16766 if (res != NULL) *res = v7_get_thrown_value(v7, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 16767 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 16768 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16769 #ifndef V7_MMAP_EXEC
Marko Mikulicic 0:c0ecb8bf28eb 16770 int fr = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16771 #else
Marko Mikulicic 0:c0ecb8bf28eb 16772 int fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16773 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16774 rcode = b_exec(v7, p, file_size, path, V7_UNDEFINED, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16775 V7_UNDEFINED, is_json, fr, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16776 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16777 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 16778 }
Marko Mikulicic 0:c0ecb8bf28eb 16779 }
Marko Mikulicic 0:c0ecb8bf28eb 16780
Marko Mikulicic 0:c0ecb8bf28eb 16781 clean:
Marko Mikulicic 0:c0ecb8bf28eb 16782 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 16783 }
Marko Mikulicic 0:c0ecb8bf28eb 16784
Marko Mikulicic 0:c0ecb8bf28eb 16785 enum v7_err v7_exec_file(struct v7 *v7, const char *path, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16786 return exec_file(v7, path, res, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16787 }
Marko Mikulicic 0:c0ecb8bf28eb 16788
Marko Mikulicic 0:c0ecb8bf28eb 16789 enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16790 return exec_file(v7, path, res, 1);
Marko Mikulicic 0:c0ecb8bf28eb 16791 }
Marko Mikulicic 0:c0ecb8bf28eb 16792 #endif /* V7_NO_FS */
Marko Mikulicic 0:c0ecb8bf28eb 16793
Marko Mikulicic 0:c0ecb8bf28eb 16794 enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 16795 v7_val_t args, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16796 return b_apply(v7, func, this_obj, args, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16797 }
Marko Mikulicic 0:c0ecb8bf28eb 16798
Marko Mikulicic 0:c0ecb8bf28eb 16799 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 16800 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 16801 enum v7_err _v7_compile(const char *src, size_t js_code_size, int binary,
Marko Mikulicic 0:c0ecb8bf28eb 16802 int use_bcode, FILE *fp) {
Marko Mikulicic 0:c0ecb8bf28eb 16803 struct ast ast;
Marko Mikulicic 0:c0ecb8bf28eb 16804 struct v7 *v7 = v7_create();
Marko Mikulicic 0:c0ecb8bf28eb 16805 ast_off_t pos = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16806 enum v7_err err;
Marko Mikulicic 0:c0ecb8bf28eb 16807
Marko Mikulicic 0:c0ecb8bf28eb 16808 v7->is_precompiling = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16809
Marko Mikulicic 0:c0ecb8bf28eb 16810 ast_init(&ast, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16811 err = parse(v7, &ast, src, js_code_size, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16812 if (err == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16813 if (use_bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 16814 struct bcode bcode;
Marko Mikulicic 0:c0ecb8bf28eb 16815 /*
Marko Mikulicic 0:c0ecb8bf28eb 16816 * We don't set filename here, because the bcode will be just serialized
Marko Mikulicic 0:c0ecb8bf28eb 16817 * and then freed. We don't currently serialize filename. If we ever do,
Marko Mikulicic 0:c0ecb8bf28eb 16818 * we'll have to make `_v7_compile()` to also take a filename argument,
Marko Mikulicic 0:c0ecb8bf28eb 16819 * and use it here.
Marko Mikulicic 0:c0ecb8bf28eb 16820 */
Marko Mikulicic 0:c0ecb8bf28eb 16821 bcode_init(&bcode, 0, NULL, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16822 err = compile_script(v7, &ast, &bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16823 if (err != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16824 goto cleanup_bcode;
Marko Mikulicic 0:c0ecb8bf28eb 16825 }
Marko Mikulicic 0:c0ecb8bf28eb 16826
Marko Mikulicic 0:c0ecb8bf28eb 16827 if (binary) {
Marko Mikulicic 0:c0ecb8bf28eb 16828 bcode_serialize(v7, &bcode, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16829 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16830 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 16831 dump_bcode(v7, fp, &bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16832 #else
Marko Mikulicic 0:c0ecb8bf28eb 16833 fprintf(stderr, "build flag V7_BCODE_DUMP not enabled\n");
Marko Mikulicic 0:c0ecb8bf28eb 16834 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16835 }
Marko Mikulicic 0:c0ecb8bf28eb 16836 cleanup_bcode:
Marko Mikulicic 0:c0ecb8bf28eb 16837 bcode_free(v7, &bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16838 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16839 if (binary) {
Marko Mikulicic 0:c0ecb8bf28eb 16840 fwrite(BIN_AST_SIGNATURE, sizeof(BIN_AST_SIGNATURE), 1, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16841 fwrite(ast.mbuf.buf, ast.mbuf.len, 1, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16842 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16843 ast_dump_tree(fp, &ast, &pos, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16844 }
Marko Mikulicic 0:c0ecb8bf28eb 16845 }
Marko Mikulicic 0:c0ecb8bf28eb 16846 }
Marko Mikulicic 0:c0ecb8bf28eb 16847
Marko Mikulicic 0:c0ecb8bf28eb 16848 ast_free(&ast);
Marko Mikulicic 0:c0ecb8bf28eb 16849 v7_destroy(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16850 return err;
Marko Mikulicic 0:c0ecb8bf28eb 16851 }
Marko Mikulicic 0:c0ecb8bf28eb 16852
Marko Mikulicic 0:c0ecb8bf28eb 16853 enum v7_err v7_compile(const char *src, int binary, int use_bcode, FILE *fp) {
Marko Mikulicic 0:c0ecb8bf28eb 16854 return _v7_compile(src, strlen(src), binary, use_bcode, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16855 }
Marko Mikulicic 0:c0ecb8bf28eb 16856 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 16857 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16858 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16859 #line 1 "v7/src/util.c"
Marko Mikulicic 0:c0ecb8bf28eb 16860 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16861 /*
Marko Mikulicic 0:c0ecb8bf28eb 16862 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16863 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16864 */
Marko Mikulicic 0:c0ecb8bf28eb 16865
Marko Mikulicic 0:c0ecb8bf28eb 16866 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16867 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16868 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16869 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16870 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16871 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16872 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16873 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16874 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16875 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16876 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16877
Marko Mikulicic 0:c0ecb8bf28eb 16878 void v7_print(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16879 v7_fprint(stdout, v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16880 }
Marko Mikulicic 0:c0ecb8bf28eb 16881
Marko Mikulicic 0:c0ecb8bf28eb 16882 void v7_fprint(FILE *f, struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16883 char buf[16];
Marko Mikulicic 0:c0ecb8bf28eb 16884 char *s = v7_stringify(v7, v, buf, sizeof(buf), V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 16885 fprintf(f, "%s", s);
Marko Mikulicic 0:c0ecb8bf28eb 16886 if (buf != s) free(s);
Marko Mikulicic 0:c0ecb8bf28eb 16887 }
Marko Mikulicic 0:c0ecb8bf28eb 16888
Marko Mikulicic 0:c0ecb8bf28eb 16889 void v7_println(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16890 v7_fprintln(stdout, v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16891 }
Marko Mikulicic 0:c0ecb8bf28eb 16892
Marko Mikulicic 0:c0ecb8bf28eb 16893 void v7_fprintln(FILE *f, struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16894 v7_fprint(f, v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16895 fprintf(f, ENDL);
Marko Mikulicic 0:c0ecb8bf28eb 16896 }
Marko Mikulicic 0:c0ecb8bf28eb 16897
Marko Mikulicic 0:c0ecb8bf28eb 16898 void v7_fprint_stack_trace(FILE *f, struct v7 *v7, val_t e) {
Marko Mikulicic 0:c0ecb8bf28eb 16899 size_t s;
Marko Mikulicic 0:c0ecb8bf28eb 16900 val_t strace_v = v7_get(v7, e, "stack", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 16901 const char *strace = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16902 if (v7_is_string(strace_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16903 strace = v7_get_string(v7, &strace_v, &s);
Marko Mikulicic 0:c0ecb8bf28eb 16904 fprintf(f, "%s\n", strace);
Marko Mikulicic 0:c0ecb8bf28eb 16905 }
Marko Mikulicic 0:c0ecb8bf28eb 16906 }
Marko Mikulicic 0:c0ecb8bf28eb 16907
Marko Mikulicic 0:c0ecb8bf28eb 16908 void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, val_t e) {
Marko Mikulicic 0:c0ecb8bf28eb 16909 /* TODO(mkm): figure out if this is an error object and which kind */
Marko Mikulicic 0:c0ecb8bf28eb 16910 v7_val_t msg;
Marko Mikulicic 0:c0ecb8bf28eb 16911 if (v7_is_undefined(e)) {
Marko Mikulicic 0:c0ecb8bf28eb 16912 fprintf(f, "undefined error [%s]\n ", ctx);
Marko Mikulicic 0:c0ecb8bf28eb 16913 return;
Marko Mikulicic 0:c0ecb8bf28eb 16914 }
Marko Mikulicic 0:c0ecb8bf28eb 16915 msg = v7_get(v7, e, "message", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 16916 if (v7_is_undefined(msg)) {
Marko Mikulicic 0:c0ecb8bf28eb 16917 msg = e;
Marko Mikulicic 0:c0ecb8bf28eb 16918 }
Marko Mikulicic 0:c0ecb8bf28eb 16919 fprintf(f, "Exec error [%s]: ", ctx);
Marko Mikulicic 0:c0ecb8bf28eb 16920 v7_fprintln(f, v7, msg);
Marko Mikulicic 0:c0ecb8bf28eb 16921 v7_fprint_stack_trace(f, v7, e);
Marko Mikulicic 0:c0ecb8bf28eb 16922 }
Marko Mikulicic 0:c0ecb8bf28eb 16923
Marko Mikulicic 0:c0ecb8bf28eb 16924 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 16925
Marko Mikulicic 0:c0ecb8bf28eb 16926 v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target,
Marko Mikulicic 0:c0ecb8bf28eb 16927 const v7_proxy_hnd_t *handler) {
Marko Mikulicic 0:c0ecb8bf28eb 16928 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 16929 v7_val_t res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16930 v7_val_t args = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16931 v7_val_t handler_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16932
Marko Mikulicic 0:c0ecb8bf28eb 16933 v7_own(v7, &res);
Marko Mikulicic 0:c0ecb8bf28eb 16934 v7_own(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 16935 v7_own(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 16936 v7_own(v7, &target);
Marko Mikulicic 0:c0ecb8bf28eb 16937
Marko Mikulicic 0:c0ecb8bf28eb 16938 /* if target is not an object, create one */
Marko Mikulicic 0:c0ecb8bf28eb 16939 if (!v7_is_object(target)) {
Marko Mikulicic 0:c0ecb8bf28eb 16940 target = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16941 }
Marko Mikulicic 0:c0ecb8bf28eb 16942
Marko Mikulicic 0:c0ecb8bf28eb 16943 /* prepare handler object with necessary properties */
Marko Mikulicic 0:c0ecb8bf28eb 16944 handler_v = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16945 if (handler->get != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16946 set_cfunc_prop(v7, handler_v, "get", handler->get);
Marko Mikulicic 0:c0ecb8bf28eb 16947 }
Marko Mikulicic 0:c0ecb8bf28eb 16948 if (handler->set != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16949 set_cfunc_prop(v7, handler_v, "set", handler->set);
Marko Mikulicic 0:c0ecb8bf28eb 16950 }
Marko Mikulicic 0:c0ecb8bf28eb 16951 if (handler->own_keys != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16952 set_cfunc_prop(v7, handler_v, "ownKeys", handler->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 16953 }
Marko Mikulicic 0:c0ecb8bf28eb 16954 if (handler->get_own_prop_desc != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16955 v7_def(v7, handler_v, "_gpdc", ~0, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 16956 v7_mk_foreign(v7, (void *) handler->get_own_prop_desc));
Marko Mikulicic 0:c0ecb8bf28eb 16957 }
Marko Mikulicic 0:c0ecb8bf28eb 16958
Marko Mikulicic 0:c0ecb8bf28eb 16959 /* prepare args */
Marko Mikulicic 0:c0ecb8bf28eb 16960 args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16961 v7_array_set(v7, args, 0, target);
Marko Mikulicic 0:c0ecb8bf28eb 16962 v7_array_set(v7, args, 1, handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 16963
Marko Mikulicic 0:c0ecb8bf28eb 16964 /* call Proxy constructor */
Marko Mikulicic 0:c0ecb8bf28eb 16965 V7_TRY(b_apply(v7, v7_get(v7, v7->vals.global_object, "Proxy", ~0),
Marko Mikulicic 0:c0ecb8bf28eb 16966 v7_mk_object(v7), args, 1 /* as ctor */, &res));
Marko Mikulicic 0:c0ecb8bf28eb 16967
Marko Mikulicic 0:c0ecb8bf28eb 16968 clean:
Marko Mikulicic 0:c0ecb8bf28eb 16969 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16970 fprintf(stderr, "error during v7_mk_proxy()");
Marko Mikulicic 0:c0ecb8bf28eb 16971 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16972 }
Marko Mikulicic 0:c0ecb8bf28eb 16973
Marko Mikulicic 0:c0ecb8bf28eb 16974 v7_disown(v7, &target);
Marko Mikulicic 0:c0ecb8bf28eb 16975 v7_disown(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 16976 v7_disown(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 16977 v7_disown(v7, &res);
Marko Mikulicic 0:c0ecb8bf28eb 16978 return res;
Marko Mikulicic 0:c0ecb8bf28eb 16979 }
Marko Mikulicic 0:c0ecb8bf28eb 16980
Marko Mikulicic 0:c0ecb8bf28eb 16981 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 16982
Marko Mikulicic 0:c0ecb8bf28eb 16983 V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16984 int tag;
Marko Mikulicic 0:c0ecb8bf28eb 16985 if (v7_is_number(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16986 return V7_TYPE_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 16987 }
Marko Mikulicic 0:c0ecb8bf28eb 16988 tag = (v & V7_TAG_MASK) >> 48;
Marko Mikulicic 0:c0ecb8bf28eb 16989 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 16990 case V7_TAG_FOREIGN >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16991 if (v7_is_null(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16992 return V7_TYPE_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16993 }
Marko Mikulicic 0:c0ecb8bf28eb 16994 return V7_TYPE_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 16995 case V7_TAG_UNDEFINED >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16996 return V7_TYPE_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16997 case V7_TAG_OBJECT >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16998 if (v7_get_proto(v7, v) == v7->vals.array_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 16999 return V7_TYPE_ARRAY_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17000 } else if (v7_get_proto(v7, v) == v7->vals.boolean_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 17001 return V7_TYPE_BOOLEAN_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17002 } else if (v7_get_proto(v7, v) == v7->vals.string_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 17003 return V7_TYPE_STRING_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17004 } else if (v7_get_proto(v7, v) == v7->vals.number_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 17005 return V7_TYPE_NUMBER_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17006 } else if (v7_get_proto(v7, v) == v7->vals.function_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 17007 return V7_TYPE_CFUNCTION_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17008 } else if (v7_get_proto(v7, v) == v7->vals.date_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 17009 return V7_TYPE_DATE_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17010 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17011 return V7_TYPE_GENERIC_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17012 }
Marko Mikulicic 0:c0ecb8bf28eb 17013 case V7_TAG_STRING_I >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17014 case V7_TAG_STRING_O >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17015 case V7_TAG_STRING_F >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17016 case V7_TAG_STRING_D >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17017 case V7_TAG_STRING_5 >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17018 return V7_TYPE_STRING;
Marko Mikulicic 0:c0ecb8bf28eb 17019 case V7_TAG_BOOLEAN >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17020 return V7_TYPE_BOOLEAN;
Marko Mikulicic 0:c0ecb8bf28eb 17021 case V7_TAG_FUNCTION >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17022 return V7_TYPE_FUNCTION_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17023 case V7_TAG_CFUNCTION >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17024 return V7_TYPE_CFUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 17025 case V7_TAG_REGEXP >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 17026 return V7_TYPE_REGEXP_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17027 default:
Marko Mikulicic 0:c0ecb8bf28eb 17028 abort();
Marko Mikulicic 0:c0ecb8bf28eb 17029 return V7_TYPE_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17030 }
Marko Mikulicic 0:c0ecb8bf28eb 17031 }
Marko Mikulicic 0:c0ecb8bf28eb 17032
Marko Mikulicic 0:c0ecb8bf28eb 17033 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 17034 V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b) {
Marko Mikulicic 0:c0ecb8bf28eb 17035 if ((b & 0x01) != (b >> 7)) {
Marko Mikulicic 0:c0ecb8bf28eb 17036 b ^= 0x81;
Marko Mikulicic 0:c0ecb8bf28eb 17037 }
Marko Mikulicic 0:c0ecb8bf28eb 17038 return b;
Marko Mikulicic 0:c0ecb8bf28eb 17039 }
Marko Mikulicic 0:c0ecb8bf28eb 17040 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17041 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 17042 #line 1 "v7/src/string.c"
Marko Mikulicic 0:c0ecb8bf28eb 17043 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17044 /*
Marko Mikulicic 0:c0ecb8bf28eb 17045 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 17046 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 17047 */
Marko Mikulicic 0:c0ecb8bf28eb 17048
Marko Mikulicic 0:c0ecb8bf28eb 17049 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17050 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17051 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17052 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17053 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17054 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17055 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17056 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17057 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17058 /* Amalgamated: #include "v7/src/heapusage.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17059
Marko Mikulicic 0:c0ecb8bf28eb 17060 /* TODO(lsm): NaN payload location depends on endianness, make crossplatform */
Marko Mikulicic 0:c0ecb8bf28eb 17061 #define GET_VAL_NAN_PAYLOAD(v) ((char *) &(v))
Marko Mikulicic 0:c0ecb8bf28eb 17062
Marko Mikulicic 0:c0ecb8bf28eb 17063 /*
Marko Mikulicic 0:c0ecb8bf28eb 17064 * Dictionary of read-only strings with length > 5.
Marko Mikulicic 0:c0ecb8bf28eb 17065 * NOTE(lsm): must be sorted lexicographically, because
Marko Mikulicic 0:c0ecb8bf28eb 17066 * v_find_string_in_dictionary performs binary search over this list.
Marko Mikulicic 0:c0ecb8bf28eb 17067 */
Marko Mikulicic 0:c0ecb8bf28eb 17068 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 17069 static const struct v7_vec_const v_dictionary_strings[] = {
Marko Mikulicic 0:c0ecb8bf28eb 17070 V7_VEC(" is not a function"),
Marko Mikulicic 0:c0ecb8bf28eb 17071 V7_VEC("Boolean"),
Marko Mikulicic 0:c0ecb8bf28eb 17072 V7_VEC("Crypto"),
Marko Mikulicic 0:c0ecb8bf28eb 17073 V7_VEC("EvalError"),
Marko Mikulicic 0:c0ecb8bf28eb 17074 V7_VEC("Function"),
Marko Mikulicic 0:c0ecb8bf28eb 17075 V7_VEC("Infinity"),
Marko Mikulicic 0:c0ecb8bf28eb 17076 V7_VEC("InternalError"),
Marko Mikulicic 0:c0ecb8bf28eb 17077 V7_VEC("LOG10E"),
Marko Mikulicic 0:c0ecb8bf28eb 17078 V7_VEC("MAX_VALUE"),
Marko Mikulicic 0:c0ecb8bf28eb 17079 V7_VEC("MIN_VALUE"),
Marko Mikulicic 0:c0ecb8bf28eb 17080 V7_VEC("NEGATIVE_INFINITY"),
Marko Mikulicic 0:c0ecb8bf28eb 17081 V7_VEC("Number"),
Marko Mikulicic 0:c0ecb8bf28eb 17082 V7_VEC("Object"),
Marko Mikulicic 0:c0ecb8bf28eb 17083 V7_VEC("POSITIVE_INFINITY"),
Marko Mikulicic 0:c0ecb8bf28eb 17084 V7_VEC("RangeError"),
Marko Mikulicic 0:c0ecb8bf28eb 17085 V7_VEC("ReferenceError"),
Marko Mikulicic 0:c0ecb8bf28eb 17086 V7_VEC("RegExp"),
Marko Mikulicic 0:c0ecb8bf28eb 17087 V7_VEC("SQRT1_2"),
Marko Mikulicic 0:c0ecb8bf28eb 17088 V7_VEC("Socket"),
Marko Mikulicic 0:c0ecb8bf28eb 17089 V7_VEC("String"),
Marko Mikulicic 0:c0ecb8bf28eb 17090 V7_VEC("SyntaxError"),
Marko Mikulicic 0:c0ecb8bf28eb 17091 V7_VEC("TypeError"),
Marko Mikulicic 0:c0ecb8bf28eb 17092 V7_VEC("UBJSON"),
Marko Mikulicic 0:c0ecb8bf28eb 17093 V7_VEC("_modcache"),
Marko Mikulicic 0:c0ecb8bf28eb 17094 V7_VEC("accept"),
Marko Mikulicic 0:c0ecb8bf28eb 17095 V7_VEC("arguments"),
Marko Mikulicic 0:c0ecb8bf28eb 17096 V7_VEC("base64_decode"),
Marko Mikulicic 0:c0ecb8bf28eb 17097 V7_VEC("base64_encode"),
Marko Mikulicic 0:c0ecb8bf28eb 17098 V7_VEC("boolean"),
Marko Mikulicic 0:c0ecb8bf28eb 17099 V7_VEC("charAt"),
Marko Mikulicic 0:c0ecb8bf28eb 17100 V7_VEC("charCodeAt"),
Marko Mikulicic 0:c0ecb8bf28eb 17101 V7_VEC("concat"),
Marko Mikulicic 0:c0ecb8bf28eb 17102 V7_VEC("configurable"),
Marko Mikulicic 0:c0ecb8bf28eb 17103 V7_VEC("connect"),
Marko Mikulicic 0:c0ecb8bf28eb 17104 V7_VEC("constructor"),
Marko Mikulicic 0:c0ecb8bf28eb 17105 V7_VEC("create"),
Marko Mikulicic 0:c0ecb8bf28eb 17106 V7_VEC("defineProperties"),
Marko Mikulicic 0:c0ecb8bf28eb 17107 V7_VEC("defineProperty"),
Marko Mikulicic 0:c0ecb8bf28eb 17108 V7_VEC("every"),
Marko Mikulicic 0:c0ecb8bf28eb 17109 V7_VEC("exists"),
Marko Mikulicic 0:c0ecb8bf28eb 17110 V7_VEC("exports"),
Marko Mikulicic 0:c0ecb8bf28eb 17111 V7_VEC("filter"),
Marko Mikulicic 0:c0ecb8bf28eb 17112 V7_VEC("forEach"),
Marko Mikulicic 0:c0ecb8bf28eb 17113 V7_VEC("fromCharCode"),
Marko Mikulicic 0:c0ecb8bf28eb 17114 V7_VEC("function"),
Marko Mikulicic 0:c0ecb8bf28eb 17115 V7_VEC("getDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17116 V7_VEC("getDay"),
Marko Mikulicic 0:c0ecb8bf28eb 17117 V7_VEC("getFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17118 V7_VEC("getHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17119 V7_VEC("getMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17120 V7_VEC("getMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17121 V7_VEC("getMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17122 V7_VEC("getOwnPropertyDescriptor"),
Marko Mikulicic 0:c0ecb8bf28eb 17123 V7_VEC("getOwnPropertyNames"),
Marko Mikulicic 0:c0ecb8bf28eb 17124 V7_VEC("getPrototypeOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17125 V7_VEC("getSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17126 V7_VEC("getTime"),
Marko Mikulicic 0:c0ecb8bf28eb 17127 V7_VEC("getTimezoneOffset"),
Marko Mikulicic 0:c0ecb8bf28eb 17128 V7_VEC("getUTCDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17129 V7_VEC("getUTCDay"),
Marko Mikulicic 0:c0ecb8bf28eb 17130 V7_VEC("getUTCFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17131 V7_VEC("getUTCHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17132 V7_VEC("getUTCMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17133 V7_VEC("getUTCMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17134 V7_VEC("getUTCMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17135 V7_VEC("getUTCSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17136 V7_VEC("global"),
Marko Mikulicic 0:c0ecb8bf28eb 17137 V7_VEC("hasOwnProperty"),
Marko Mikulicic 0:c0ecb8bf28eb 17138 V7_VEC("ignoreCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17139 V7_VEC("indexOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17140 V7_VEC("isArray"),
Marko Mikulicic 0:c0ecb8bf28eb 17141 V7_VEC("isExtensible"),
Marko Mikulicic 0:c0ecb8bf28eb 17142 V7_VEC("isFinite"),
Marko Mikulicic 0:c0ecb8bf28eb 17143 V7_VEC("isPrototypeOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17144 V7_VEC("lastIndex"),
Marko Mikulicic 0:c0ecb8bf28eb 17145 V7_VEC("lastIndexOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17146 V7_VEC("length"),
Marko Mikulicic 0:c0ecb8bf28eb 17147 V7_VEC("listen"),
Marko Mikulicic 0:c0ecb8bf28eb 17148 V7_VEC("loadJSON"),
Marko Mikulicic 0:c0ecb8bf28eb 17149 V7_VEC("localeCompare"),
Marko Mikulicic 0:c0ecb8bf28eb 17150 V7_VEC("md5_hex"),
Marko Mikulicic 0:c0ecb8bf28eb 17151 V7_VEC("module"),
Marko Mikulicic 0:c0ecb8bf28eb 17152 V7_VEC("multiline"),
Marko Mikulicic 0:c0ecb8bf28eb 17153 V7_VEC("number"),
Marko Mikulicic 0:c0ecb8bf28eb 17154 V7_VEC("parseFloat"),
Marko Mikulicic 0:c0ecb8bf28eb 17155 V7_VEC("parseInt"),
Marko Mikulicic 0:c0ecb8bf28eb 17156 V7_VEC("preventExtensions"),
Marko Mikulicic 0:c0ecb8bf28eb 17157 V7_VEC("propertyIsEnumerable"),
Marko Mikulicic 0:c0ecb8bf28eb 17158 V7_VEC("prototype"),
Marko Mikulicic 0:c0ecb8bf28eb 17159 V7_VEC("random"),
Marko Mikulicic 0:c0ecb8bf28eb 17160 V7_VEC("recvAll"),
Marko Mikulicic 0:c0ecb8bf28eb 17161 V7_VEC("reduce"),
Marko Mikulicic 0:c0ecb8bf28eb 17162 V7_VEC("remove"),
Marko Mikulicic 0:c0ecb8bf28eb 17163 V7_VEC("rename"),
Marko Mikulicic 0:c0ecb8bf28eb 17164 V7_VEC("render"),
Marko Mikulicic 0:c0ecb8bf28eb 17165 V7_VEC("replace"),
Marko Mikulicic 0:c0ecb8bf28eb 17166 V7_VEC("require"),
Marko Mikulicic 0:c0ecb8bf28eb 17167 V7_VEC("reverse"),
Marko Mikulicic 0:c0ecb8bf28eb 17168 V7_VEC("search"),
Marko Mikulicic 0:c0ecb8bf28eb 17169 V7_VEC("setDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17170 V7_VEC("setFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17171 V7_VEC("setHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17172 V7_VEC("setMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17173 V7_VEC("setMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17174 V7_VEC("setMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17175 V7_VEC("setSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17176 V7_VEC("setTime"),
Marko Mikulicic 0:c0ecb8bf28eb 17177 V7_VEC("setUTCDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17178 V7_VEC("setUTCFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17179 V7_VEC("setUTCHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17180 V7_VEC("setUTCMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17181 V7_VEC("setUTCMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17182 V7_VEC("setUTCMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17183 V7_VEC("setUTCSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17184 V7_VEC("sha1_hex"),
Marko Mikulicic 0:c0ecb8bf28eb 17185 V7_VEC("source"),
Marko Mikulicic 0:c0ecb8bf28eb 17186 V7_VEC("splice"),
Marko Mikulicic 0:c0ecb8bf28eb 17187 V7_VEC("string"),
Marko Mikulicic 0:c0ecb8bf28eb 17188 V7_VEC("stringify"),
Marko Mikulicic 0:c0ecb8bf28eb 17189 V7_VEC("substr"),
Marko Mikulicic 0:c0ecb8bf28eb 17190 V7_VEC("substring"),
Marko Mikulicic 0:c0ecb8bf28eb 17191 V7_VEC("toDateString"),
Marko Mikulicic 0:c0ecb8bf28eb 17192 V7_VEC("toExponential"),
Marko Mikulicic 0:c0ecb8bf28eb 17193 V7_VEC("toFixed"),
Marko Mikulicic 0:c0ecb8bf28eb 17194 V7_VEC("toISOString"),
Marko Mikulicic 0:c0ecb8bf28eb 17195 V7_VEC("toJSON"),
Marko Mikulicic 0:c0ecb8bf28eb 17196 V7_VEC("toLocaleDateString"),
Marko Mikulicic 0:c0ecb8bf28eb 17197 V7_VEC("toLocaleLowerCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17198 V7_VEC("toLocaleString"),
Marko Mikulicic 0:c0ecb8bf28eb 17199 V7_VEC("toLocaleTimeString"),
Marko Mikulicic 0:c0ecb8bf28eb 17200 V7_VEC("toLocaleUpperCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17201 V7_VEC("toLowerCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17202 V7_VEC("toPrecision"),
Marko Mikulicic 0:c0ecb8bf28eb 17203 V7_VEC("toString"),
Marko Mikulicic 0:c0ecb8bf28eb 17204 V7_VEC("toTimeString"),
Marko Mikulicic 0:c0ecb8bf28eb 17205 V7_VEC("toUTCString"),
Marko Mikulicic 0:c0ecb8bf28eb 17206 V7_VEC("toUpperCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17207 V7_VEC("valueOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17208 V7_VEC("writable"),
Marko Mikulicic 0:c0ecb8bf28eb 17209 };
Marko Mikulicic 0:c0ecb8bf28eb 17210 /* clang-format on */
Marko Mikulicic 0:c0ecb8bf28eb 17211
Marko Mikulicic 0:c0ecb8bf28eb 17212 int nextesc(const char **p); /* from SLRE */
Marko Mikulicic 0:c0ecb8bf28eb 17213 V7_PRIVATE size_t unescape(const char *s, size_t len, char *to) {
Marko Mikulicic 0:c0ecb8bf28eb 17214 const char *end = s + len;
Marko Mikulicic 0:c0ecb8bf28eb 17215 size_t n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17216 char tmp[4];
Marko Mikulicic 0:c0ecb8bf28eb 17217 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 17218
Marko Mikulicic 0:c0ecb8bf28eb 17219 while (s < end) {
Marko Mikulicic 0:c0ecb8bf28eb 17220 s += chartorune(&r, s);
Marko Mikulicic 0:c0ecb8bf28eb 17221 if (r == '\\' && s < end) {
Marko Mikulicic 0:c0ecb8bf28eb 17222 switch (*s) {
Marko Mikulicic 0:c0ecb8bf28eb 17223 case '"':
Marko Mikulicic 0:c0ecb8bf28eb 17224 s++, r = '"';
Marko Mikulicic 0:c0ecb8bf28eb 17225 break;
Marko Mikulicic 0:c0ecb8bf28eb 17226 case '\'':
Marko Mikulicic 0:c0ecb8bf28eb 17227 s++, r = '\'';
Marko Mikulicic 0:c0ecb8bf28eb 17228 break;
Marko Mikulicic 0:c0ecb8bf28eb 17229 case '\n':
Marko Mikulicic 0:c0ecb8bf28eb 17230 s++, r = '\n';
Marko Mikulicic 0:c0ecb8bf28eb 17231 break;
Marko Mikulicic 0:c0ecb8bf28eb 17232 default: {
Marko Mikulicic 0:c0ecb8bf28eb 17233 const char *tmp_s = s;
Marko Mikulicic 0:c0ecb8bf28eb 17234 int i = nextesc(&s);
Marko Mikulicic 0:c0ecb8bf28eb 17235 switch (i) {
Marko Mikulicic 0:c0ecb8bf28eb 17236 case -SLRE_INVALID_ESC_CHAR:
Marko Mikulicic 0:c0ecb8bf28eb 17237 r = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 17238 s = tmp_s;
Marko Mikulicic 0:c0ecb8bf28eb 17239 n += runetochar(to == NULL ? tmp : to + n, &r);
Marko Mikulicic 0:c0ecb8bf28eb 17240 s += chartorune(&r, s);
Marko Mikulicic 0:c0ecb8bf28eb 17241 break;
Marko Mikulicic 0:c0ecb8bf28eb 17242 case -SLRE_INVALID_HEX_DIGIT:
Marko Mikulicic 0:c0ecb8bf28eb 17243 default:
Marko Mikulicic 0:c0ecb8bf28eb 17244 r = i;
Marko Mikulicic 0:c0ecb8bf28eb 17245 }
Marko Mikulicic 0:c0ecb8bf28eb 17246 }
Marko Mikulicic 0:c0ecb8bf28eb 17247 }
Marko Mikulicic 0:c0ecb8bf28eb 17248 }
Marko Mikulicic 0:c0ecb8bf28eb 17249 n += runetochar(to == NULL ? tmp : to + n, &r);
Marko Mikulicic 0:c0ecb8bf28eb 17250 }
Marko Mikulicic 0:c0ecb8bf28eb 17251
Marko Mikulicic 0:c0ecb8bf28eb 17252 return n;
Marko Mikulicic 0:c0ecb8bf28eb 17253 }
Marko Mikulicic 0:c0ecb8bf28eb 17254
Marko Mikulicic 0:c0ecb8bf28eb 17255 static int v_find_string_in_dictionary(const char *s, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 17256 size_t start = 0, end = ARRAY_SIZE(v_dictionary_strings);
Marko Mikulicic 0:c0ecb8bf28eb 17257
Marko Mikulicic 0:c0ecb8bf28eb 17258 while (s != NULL && start < end) {
Marko Mikulicic 0:c0ecb8bf28eb 17259 size_t mid = start + (end - start) / 2;
Marko Mikulicic 0:c0ecb8bf28eb 17260 const struct v7_vec_const *v = &v_dictionary_strings[mid];
Marko Mikulicic 0:c0ecb8bf28eb 17261 size_t min_len = len < v->len ? len : v->len;
Marko Mikulicic 0:c0ecb8bf28eb 17262 int comparison_result = memcmp(s, v->p, min_len);
Marko Mikulicic 0:c0ecb8bf28eb 17263 if (comparison_result == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17264 comparison_result = len - v->len;
Marko Mikulicic 0:c0ecb8bf28eb 17265 }
Marko Mikulicic 0:c0ecb8bf28eb 17266 if (comparison_result < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17267 end = mid;
Marko Mikulicic 0:c0ecb8bf28eb 17268 } else if (comparison_result > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17269 start = mid + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17270 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17271 return mid;
Marko Mikulicic 0:c0ecb8bf28eb 17272 }
Marko Mikulicic 0:c0ecb8bf28eb 17273 }
Marko Mikulicic 0:c0ecb8bf28eb 17274 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 17275 }
Marko Mikulicic 0:c0ecb8bf28eb 17276
Marko Mikulicic 0:c0ecb8bf28eb 17277 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 17278 V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, val_t obj, val_t arg,
Marko Mikulicic 0:c0ecb8bf28eb 17279 double *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17280 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17281 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 17282 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17283 const char *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17284 double at = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 17285
Marko Mikulicic 0:c0ecb8bf28eb 17286 *res = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17287
Marko Mikulicic 0:c0ecb8bf28eb 17288 rcode = to_string(v7, obj, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17289 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 17290 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17291 }
Marko Mikulicic 0:c0ecb8bf28eb 17292
Marko Mikulicic 0:c0ecb8bf28eb 17293 p = v7_get_string(v7, &s, &n);
Marko Mikulicic 0:c0ecb8bf28eb 17294
Marko Mikulicic 0:c0ecb8bf28eb 17295 n = utfnlen(p, n);
Marko Mikulicic 0:c0ecb8bf28eb 17296 if (v7_is_number(arg) && at >= 0 && at < n) {
Marko Mikulicic 0:c0ecb8bf28eb 17297 Rune r = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17298 p = utfnshift(p, at);
Marko Mikulicic 0:c0ecb8bf28eb 17299 chartorune(&r, (char *) p);
Marko Mikulicic 0:c0ecb8bf28eb 17300 *res = r;
Marko Mikulicic 0:c0ecb8bf28eb 17301 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17302 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17303 *res = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 17304 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17305 }
Marko Mikulicic 0:c0ecb8bf28eb 17306
Marko Mikulicic 0:c0ecb8bf28eb 17307 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17308 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17309 }
Marko Mikulicic 0:c0ecb8bf28eb 17310
Marko Mikulicic 0:c0ecb8bf28eb 17311 V7_PRIVATE int s_cmp(struct v7 *v7, val_t a, val_t b) {
Marko Mikulicic 0:c0ecb8bf28eb 17312 size_t a_len, b_len;
Marko Mikulicic 0:c0ecb8bf28eb 17313 const char *a_ptr, *b_ptr;
Marko Mikulicic 0:c0ecb8bf28eb 17314
Marko Mikulicic 0:c0ecb8bf28eb 17315 a_ptr = v7_get_string(v7, &a, &a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17316 b_ptr = v7_get_string(v7, &b, &b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17317
Marko Mikulicic 0:c0ecb8bf28eb 17318 if (a_len == b_len) {
Marko Mikulicic 0:c0ecb8bf28eb 17319 return memcmp(a_ptr, b_ptr, a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17320 }
Marko Mikulicic 0:c0ecb8bf28eb 17321 if (a_len > b_len) {
Marko Mikulicic 0:c0ecb8bf28eb 17322 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 17323 } else if (a_len < b_len) {
Marko Mikulicic 0:c0ecb8bf28eb 17324 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 17325 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17326 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 17327 }
Marko Mikulicic 0:c0ecb8bf28eb 17328 }
Marko Mikulicic 0:c0ecb8bf28eb 17329
Marko Mikulicic 0:c0ecb8bf28eb 17330 V7_PRIVATE val_t s_concat(struct v7 *v7, val_t a, val_t b) {
Marko Mikulicic 0:c0ecb8bf28eb 17331 size_t a_len, b_len, res_len;
Marko Mikulicic 0:c0ecb8bf28eb 17332 const char *a_ptr, *b_ptr, *res_ptr;
Marko Mikulicic 0:c0ecb8bf28eb 17333 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 17334
Marko Mikulicic 0:c0ecb8bf28eb 17335 /* Find out lengths of both srtings */
Marko Mikulicic 0:c0ecb8bf28eb 17336 a_ptr = v7_get_string(v7, &a, &a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17337 b_ptr = v7_get_string(v7, &b, &b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17338
Marko Mikulicic 0:c0ecb8bf28eb 17339 /* Create an placeholder string */
Marko Mikulicic 0:c0ecb8bf28eb 17340 res = v7_mk_string(v7, NULL, a_len + b_len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 17341
Marko Mikulicic 0:c0ecb8bf28eb 17342 /* v7_mk_string() may have reallocated mbuf - revalidate pointers */
Marko Mikulicic 0:c0ecb8bf28eb 17343 a_ptr = v7_get_string(v7, &a, &a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17344 b_ptr = v7_get_string(v7, &b, &b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17345
Marko Mikulicic 0:c0ecb8bf28eb 17346 /* Copy strings into the placeholder */
Marko Mikulicic 0:c0ecb8bf28eb 17347 res_ptr = v7_get_string(v7, &res, &res_len);
Marko Mikulicic 0:c0ecb8bf28eb 17348 memcpy((char *) res_ptr, a_ptr, a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17349 memcpy((char *) res_ptr + a_len, b_ptr, b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17350
Marko Mikulicic 0:c0ecb8bf28eb 17351 return res;
Marko Mikulicic 0:c0ecb8bf28eb 17352 }
Marko Mikulicic 0:c0ecb8bf28eb 17353
Marko Mikulicic 0:c0ecb8bf28eb 17354 V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok) {
Marko Mikulicic 0:c0ecb8bf28eb 17355 char *e;
Marko Mikulicic 0:c0ecb8bf28eb 17356 unsigned long res = strtoul(s, &e, 10);
Marko Mikulicic 0:c0ecb8bf28eb 17357 *ok = (e == s + len) && len != 0;
Marko Mikulicic 0:c0ecb8bf28eb 17358 return res;
Marko Mikulicic 0:c0ecb8bf28eb 17359 }
Marko Mikulicic 0:c0ecb8bf28eb 17360
Marko Mikulicic 0:c0ecb8bf28eb 17361 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 17362 V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok,
Marko Mikulicic 0:c0ecb8bf28eb 17363 unsigned long *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17364 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17365 char buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 17366 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17367
Marko Mikulicic 0:c0ecb8bf28eb 17368 V7_TRY(to_string(v7, v, NULL, buf, sizeof(buf), &len));
Marko Mikulicic 0:c0ecb8bf28eb 17369
Marko Mikulicic 0:c0ecb8bf28eb 17370 *res = cstr_to_ulong(buf, len, ok);
Marko Mikulicic 0:c0ecb8bf28eb 17371
Marko Mikulicic 0:c0ecb8bf28eb 17372 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17373 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17374 }
Marko Mikulicic 0:c0ecb8bf28eb 17375
Marko Mikulicic 0:c0ecb8bf28eb 17376 /* Insert a string into mbuf at specified offset */
Marko Mikulicic 0:c0ecb8bf28eb 17377 V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p,
Marko Mikulicic 0:c0ecb8bf28eb 17378 size_t len, uint8_t /*enum embstr_flags*/ flags) {
Marko Mikulicic 0:c0ecb8bf28eb 17379 char *old_base = m->buf;
Marko Mikulicic 0:c0ecb8bf28eb 17380 uint8_t p_backed_by_mbuf = p >= old_base && p < old_base + m->len;
Marko Mikulicic 0:c0ecb8bf28eb 17381 size_t n = (flags & EMBSTR_UNESCAPE) ? unescape(p, len, NULL) : len;
Marko Mikulicic 0:c0ecb8bf28eb 17382
Marko Mikulicic 0:c0ecb8bf28eb 17383 /* Calculate how many bytes length takes */
Marko Mikulicic 0:c0ecb8bf28eb 17384 int k = calc_llen(n);
Marko Mikulicic 0:c0ecb8bf28eb 17385
Marko Mikulicic 0:c0ecb8bf28eb 17386 /* total length: varing length + string len + zero-term */
Marko Mikulicic 0:c0ecb8bf28eb 17387 size_t tot_len = k + n + !!(flags & EMBSTR_ZERO_TERM);
Marko Mikulicic 0:c0ecb8bf28eb 17388
Marko Mikulicic 0:c0ecb8bf28eb 17389 /* Allocate buffer */
Marko Mikulicic 0:c0ecb8bf28eb 17390 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 17391 mbuf_insert(m, offset, NULL, tot_len);
Marko Mikulicic 0:c0ecb8bf28eb 17392 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 17393
Marko Mikulicic 0:c0ecb8bf28eb 17394 /* Fixup p if it was relocated by mbuf_insert() above */
Marko Mikulicic 0:c0ecb8bf28eb 17395 if (p_backed_by_mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 17396 p += m->buf - old_base;
Marko Mikulicic 0:c0ecb8bf28eb 17397 }
Marko Mikulicic 0:c0ecb8bf28eb 17398
Marko Mikulicic 0:c0ecb8bf28eb 17399 /* Write length */
Marko Mikulicic 0:c0ecb8bf28eb 17400 encode_varint(n, (unsigned char *) m->buf + offset);
Marko Mikulicic 0:c0ecb8bf28eb 17401
Marko Mikulicic 0:c0ecb8bf28eb 17402 /* Write string */
Marko Mikulicic 0:c0ecb8bf28eb 17403 if (p != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17404 if (flags & EMBSTR_UNESCAPE) {
Marko Mikulicic 0:c0ecb8bf28eb 17405 unescape(p, len, m->buf + offset + k);
Marko Mikulicic 0:c0ecb8bf28eb 17406 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17407 memcpy(m->buf + offset + k, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 17408 }
Marko Mikulicic 0:c0ecb8bf28eb 17409 }
Marko Mikulicic 0:c0ecb8bf28eb 17410
Marko Mikulicic 0:c0ecb8bf28eb 17411 /* add NULL-terminator if needed */
Marko Mikulicic 0:c0ecb8bf28eb 17412 if (flags & EMBSTR_ZERO_TERM) {
Marko Mikulicic 0:c0ecb8bf28eb 17413 m->buf[offset + tot_len - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 17414 }
Marko Mikulicic 0:c0ecb8bf28eb 17415 }
Marko Mikulicic 0:c0ecb8bf28eb 17416
Marko Mikulicic 0:c0ecb8bf28eb 17417 /* Create a string */
Marko Mikulicic 0:c0ecb8bf28eb 17418 v7_val_t v7_mk_string(struct v7 *v7, const char *p, size_t len, int copy) {
Marko Mikulicic 0:c0ecb8bf28eb 17419 struct mbuf *m = copy ? &v7->owned_strings : &v7->foreign_strings;
Marko Mikulicic 0:c0ecb8bf28eb 17420 val_t offset = m->len, tag = V7_TAG_STRING_F;
Marko Mikulicic 0:c0ecb8bf28eb 17421 int dict_index;
Marko Mikulicic 0:c0ecb8bf28eb 17422
Marko Mikulicic 0:c0ecb8bf28eb 17423 #ifdef V7_GC_AFTER_STRING_ALLOC
Marko Mikulicic 0:c0ecb8bf28eb 17424 v7->need_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 17425 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17426
Marko Mikulicic 0:c0ecb8bf28eb 17427 if (len == ~((size_t) 0)) len = strlen(p);
Marko Mikulicic 0:c0ecb8bf28eb 17428
Marko Mikulicic 0:c0ecb8bf28eb 17429 if (len <= 4) {
Marko Mikulicic 0:c0ecb8bf28eb 17430 char *s = GET_VAL_NAN_PAYLOAD(offset) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17431 offset = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17432 if (p != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17433 memcpy(s, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 17434 }
Marko Mikulicic 0:c0ecb8bf28eb 17435 s[-1] = len;
Marko Mikulicic 0:c0ecb8bf28eb 17436 tag = V7_TAG_STRING_I;
Marko Mikulicic 0:c0ecb8bf28eb 17437 } else if (len == 5) {
Marko Mikulicic 0:c0ecb8bf28eb 17438 char *s = GET_VAL_NAN_PAYLOAD(offset);
Marko Mikulicic 0:c0ecb8bf28eb 17439 offset = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17440 if (p != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17441 memcpy(s, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 17442 }
Marko Mikulicic 0:c0ecb8bf28eb 17443 tag = V7_TAG_STRING_5;
Marko Mikulicic 0:c0ecb8bf28eb 17444 } else if ((dict_index = v_find_string_in_dictionary(p, len)) >= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17445 offset = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17446 GET_VAL_NAN_PAYLOAD(offset)[0] = dict_index;
Marko Mikulicic 0:c0ecb8bf28eb 17447 tag = V7_TAG_STRING_D;
Marko Mikulicic 0:c0ecb8bf28eb 17448 } else if (copy) {
Marko Mikulicic 0:c0ecb8bf28eb 17449 compute_need_gc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17450
Marko Mikulicic 0:c0ecb8bf28eb 17451 /*
Marko Mikulicic 0:c0ecb8bf28eb 17452 * Before embedding new string, check if the reallocation is needed. If
Marko Mikulicic 0:c0ecb8bf28eb 17453 * so, perform the reallocation by calling `mbuf_resize` manually, since we
Marko Mikulicic 0:c0ecb8bf28eb 17454 * need to preallocate some extra space (`_V7_STRING_BUF_RESERVE`)
Marko Mikulicic 0:c0ecb8bf28eb 17455 */
Marko Mikulicic 0:c0ecb8bf28eb 17456 if ((m->len + len) > m->size) {
Marko Mikulicic 0:c0ecb8bf28eb 17457 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 17458 mbuf_resize(m, m->len + len + _V7_STRING_BUF_RESERVE);
Marko Mikulicic 0:c0ecb8bf28eb 17459 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 17460 }
Marko Mikulicic 0:c0ecb8bf28eb 17461 embed_string(m, m->len, p, len, EMBSTR_ZERO_TERM);
Marko Mikulicic 0:c0ecb8bf28eb 17462 tag = V7_TAG_STRING_O;
Marko Mikulicic 0:c0ecb8bf28eb 17463 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 17464 /* TODO(imax): panic if offset >= 2^32. */
Marko Mikulicic 0:c0ecb8bf28eb 17465 offset |= ((val_t) gc_next_allocation_seqn(v7, p, len)) << 32;
Marko Mikulicic 0:c0ecb8bf28eb 17466 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17467 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17468 /* foreign string */
Marko Mikulicic 0:c0ecb8bf28eb 17469 if (sizeof(void *) <= 4 && len <= UINT16_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 17470 /* small foreign strings can fit length and ptr in the val_t */
Marko Mikulicic 0:c0ecb8bf28eb 17471 offset = (uint64_t) len << 32 | (uint64_t)(uintptr_t) p;
Marko Mikulicic 0:c0ecb8bf28eb 17472 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17473 /* bigger strings need indirection that uses ram */
Marko Mikulicic 0:c0ecb8bf28eb 17474 size_t pos = m->len;
Marko Mikulicic 0:c0ecb8bf28eb 17475 int llen = calc_llen(len);
Marko Mikulicic 0:c0ecb8bf28eb 17476
Marko Mikulicic 0:c0ecb8bf28eb 17477 /* allocate space for len and ptr */
Marko Mikulicic 0:c0ecb8bf28eb 17478 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 17479 mbuf_insert(m, pos, NULL, llen + sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 17480 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 17481
Marko Mikulicic 0:c0ecb8bf28eb 17482 encode_varint(len, (uint8_t *) (m->buf + pos));
Marko Mikulicic 0:c0ecb8bf28eb 17483 memcpy(m->buf + pos + llen, &p, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 17484 }
Marko Mikulicic 0:c0ecb8bf28eb 17485 tag = V7_TAG_STRING_F;
Marko Mikulicic 0:c0ecb8bf28eb 17486 }
Marko Mikulicic 0:c0ecb8bf28eb 17487
Marko Mikulicic 0:c0ecb8bf28eb 17488 /* NOTE(lsm): don't use pointer_to_value, 32-bit ptrs will truncate */
Marko Mikulicic 0:c0ecb8bf28eb 17489 return (offset & ~V7_TAG_MASK) | tag;
Marko Mikulicic 0:c0ecb8bf28eb 17490 }
Marko Mikulicic 0:c0ecb8bf28eb 17491
Marko Mikulicic 0:c0ecb8bf28eb 17492 int v7_is_string(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17493 uint64_t t = v & V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 17494 return t == V7_TAG_STRING_I || t == V7_TAG_STRING_F || t == V7_TAG_STRING_O ||
Marko Mikulicic 0:c0ecb8bf28eb 17495 t == V7_TAG_STRING_5 || t == V7_TAG_STRING_D;
Marko Mikulicic 0:c0ecb8bf28eb 17496 }
Marko Mikulicic 0:c0ecb8bf28eb 17497
Marko Mikulicic 0:c0ecb8bf28eb 17498 /* Get a pointer to string and string length. */
Marko Mikulicic 0:c0ecb8bf28eb 17499 const char *v7_get_string(struct v7 *v7, val_t *v, size_t *sizep) {
Marko Mikulicic 0:c0ecb8bf28eb 17500 uint64_t tag = v[0] & V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 17501 const char *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17502 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 17503 size_t size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17504
Marko Mikulicic 0:c0ecb8bf28eb 17505 if (!v7_is_string(*v)) {
Marko Mikulicic 0:c0ecb8bf28eb 17506 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17507 }
Marko Mikulicic 0:c0ecb8bf28eb 17508
Marko Mikulicic 0:c0ecb8bf28eb 17509 if (tag == V7_TAG_STRING_I) {
Marko Mikulicic 0:c0ecb8bf28eb 17510 p = GET_VAL_NAN_PAYLOAD(*v) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17511 size = p[-1];
Marko Mikulicic 0:c0ecb8bf28eb 17512 } else if (tag == V7_TAG_STRING_5) {
Marko Mikulicic 0:c0ecb8bf28eb 17513 p = GET_VAL_NAN_PAYLOAD(*v);
Marko Mikulicic 0:c0ecb8bf28eb 17514 size = 5;
Marko Mikulicic 0:c0ecb8bf28eb 17515 } else if (tag == V7_TAG_STRING_D) {
Marko Mikulicic 0:c0ecb8bf28eb 17516 int index = ((unsigned char *) GET_VAL_NAN_PAYLOAD(*v))[0];
Marko Mikulicic 0:c0ecb8bf28eb 17517 size = v_dictionary_strings[index].len;
Marko Mikulicic 0:c0ecb8bf28eb 17518 p = v_dictionary_strings[index].p;
Marko Mikulicic 0:c0ecb8bf28eb 17519 } else if (tag == V7_TAG_STRING_O) {
Marko Mikulicic 0:c0ecb8bf28eb 17520 size_t offset = (size_t) gc_string_val_to_offset(*v);
Marko Mikulicic 0:c0ecb8bf28eb 17521 char *s = v7->owned_strings.buf + offset;
Marko Mikulicic 0:c0ecb8bf28eb 17522
Marko Mikulicic 0:c0ecb8bf28eb 17523 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 17524 gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 17525 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17526
Marko Mikulicic 0:c0ecb8bf28eb 17527 size = decode_varint((uint8_t *) s, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 17528 p = s + llen;
Marko Mikulicic 0:c0ecb8bf28eb 17529 } else if (tag == V7_TAG_STRING_F) {
Marko Mikulicic 0:c0ecb8bf28eb 17530 /*
Marko Mikulicic 0:c0ecb8bf28eb 17531 * short foreign strings on <=32-bit machines can be encoded in a compact
Marko Mikulicic 0:c0ecb8bf28eb 17532 * form:
Marko Mikulicic 0:c0ecb8bf28eb 17533 *
Marko Mikulicic 0:c0ecb8bf28eb 17534 * 7 6 5 4 3 2 1 0
Marko Mikulicic 0:c0ecb8bf28eb 17535 * 11111111|1111tttt|llllllll|llllllll|ssssssss|ssssssss|ssssssss|ssssssss
Marko Mikulicic 0:c0ecb8bf28eb 17536 *
Marko Mikulicic 0:c0ecb8bf28eb 17537 * Strings longer than 2^26 will be indireceted through the foreign_strings
Marko Mikulicic 0:c0ecb8bf28eb 17538 * mbuf.
Marko Mikulicic 0:c0ecb8bf28eb 17539 *
Marko Mikulicic 0:c0ecb8bf28eb 17540 * We don't use a different tag to represent those two cases. Instead, all
Marko Mikulicic 0:c0ecb8bf28eb 17541 * foreign strings represented with the help of the foreign_strings mbuf
Marko Mikulicic 0:c0ecb8bf28eb 17542 * will have the upper 16-bits of the payload set to zero. This allows us to
Marko Mikulicic 0:c0ecb8bf28eb 17543 * represent up to 477 million foreign strings longer than 64k.
Marko Mikulicic 0:c0ecb8bf28eb 17544 */
Marko Mikulicic 0:c0ecb8bf28eb 17545 uint16_t len = (*v >> 32) & 0xFFFF;
Marko Mikulicic 0:c0ecb8bf28eb 17546 if (sizeof(void *) <= 4 && len != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17547 size = (size_t) len;
Marko Mikulicic 0:c0ecb8bf28eb 17548 p = (const char *) (uintptr_t) *v;
Marko Mikulicic 0:c0ecb8bf28eb 17549 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17550 size_t offset = (size_t) gc_string_val_to_offset(*v);
Marko Mikulicic 0:c0ecb8bf28eb 17551 char *s = v7->foreign_strings.buf + offset;
Marko Mikulicic 0:c0ecb8bf28eb 17552
Marko Mikulicic 0:c0ecb8bf28eb 17553 size = decode_varint((uint8_t *) s, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 17554 memcpy(&p, s + llen, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 17555 }
Marko Mikulicic 0:c0ecb8bf28eb 17556 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17557 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 17558 }
Marko Mikulicic 0:c0ecb8bf28eb 17559
Marko Mikulicic 0:c0ecb8bf28eb 17560 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17561 if (sizep != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17562 *sizep = size;
Marko Mikulicic 0:c0ecb8bf28eb 17563 }
Marko Mikulicic 0:c0ecb8bf28eb 17564 return p;
Marko Mikulicic 0:c0ecb8bf28eb 17565 }
Marko Mikulicic 0:c0ecb8bf28eb 17566
Marko Mikulicic 0:c0ecb8bf28eb 17567 const char *v7_get_cstring(struct v7 *v7, v7_val_t *value) {
Marko Mikulicic 0:c0ecb8bf28eb 17568 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 17569 const char *s = v7_get_string(v7, value, &size);
Marko Mikulicic 0:c0ecb8bf28eb 17570 if (s == NULL) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17571 if (s[size] != 0 || strlen(s) != size) {
Marko Mikulicic 0:c0ecb8bf28eb 17572 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17573 }
Marko Mikulicic 0:c0ecb8bf28eb 17574 return s;
Marko Mikulicic 0:c0ecb8bf28eb 17575 }
Marko Mikulicic 0:c0ecb8bf28eb 17576 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 17577 #line 1 "v7/src/array.c"
Marko Mikulicic 0:c0ecb8bf28eb 17578 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17579 /*
Marko Mikulicic 0:c0ecb8bf28eb 17580 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 17581 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 17582 */
Marko Mikulicic 0:c0ecb8bf28eb 17583
Marko Mikulicic 0:c0ecb8bf28eb 17584 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17585 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17586 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17587 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17588 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17589 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17590 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17591 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17592
Marko Mikulicic 0:c0ecb8bf28eb 17593 /* like c_snprintf but returns `size` if write is truncated */
Marko Mikulicic 0:c0ecb8bf28eb 17594 static int v_sprintf_s(char *buf, size_t size, const char *fmt, ...) {
Marko Mikulicic 0:c0ecb8bf28eb 17595 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 17596 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 17597 va_start(ap, fmt);
Marko Mikulicic 0:c0ecb8bf28eb 17598 n = c_vsnprintf(buf, size, fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 17599 if (n > size) {
Marko Mikulicic 0:c0ecb8bf28eb 17600 return size;
Marko Mikulicic 0:c0ecb8bf28eb 17601 }
Marko Mikulicic 0:c0ecb8bf28eb 17602 return n;
Marko Mikulicic 0:c0ecb8bf28eb 17603 }
Marko Mikulicic 0:c0ecb8bf28eb 17604
Marko Mikulicic 0:c0ecb8bf28eb 17605 v7_val_t v7_mk_array(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 17606 val_t a = mk_object(v7, v7->vals.array_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 17607 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 17608 v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17609 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17610 return a;
Marko Mikulicic 0:c0ecb8bf28eb 17611 }
Marko Mikulicic 0:c0ecb8bf28eb 17612
Marko Mikulicic 0:c0ecb8bf28eb 17613 int v7_is_array(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17614 return v7_is_generic_object(v) &&
Marko Mikulicic 0:c0ecb8bf28eb 17615 is_prototype_of(v7, v, v7->vals.array_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 17616 }
Marko Mikulicic 0:c0ecb8bf28eb 17617
Marko Mikulicic 0:c0ecb8bf28eb 17618 /*
Marko Mikulicic 0:c0ecb8bf28eb 17619 * Dense arrays are backed by mbuf. Currently the array can only grow by
Marko Mikulicic 0:c0ecb8bf28eb 17620 * appending (i.e. setting an element whose index == array.length)
Marko Mikulicic 0:c0ecb8bf28eb 17621 *
Marko Mikulicic 0:c0ecb8bf28eb 17622 * TODO(mkm): automatically promote dense arrays to normal objects
Marko Mikulicic 0:c0ecb8bf28eb 17623 * when they are used as sparse arrays or to store arbitrary keys
Marko Mikulicic 0:c0ecb8bf28eb 17624 * (perhaps a hybrid approach)
Marko Mikulicic 0:c0ecb8bf28eb 17625 * TODO(mkm): small sparsness doesn't have to promote the array,
Marko Mikulicic 0:c0ecb8bf28eb 17626 * we can just fill empty slots with a tag. In JS missing array
Marko Mikulicic 0:c0ecb8bf28eb 17627 * indices are subtly different from indices with an undefined value
Marko Mikulicic 0:c0ecb8bf28eb 17628 * (key iteration).
Marko Mikulicic 0:c0ecb8bf28eb 17629 * TODO(mkm): change the interpreter so it can set elements in dense arrays
Marko Mikulicic 0:c0ecb8bf28eb 17630 */
Marko Mikulicic 0:c0ecb8bf28eb 17631 V7_PRIVATE val_t v7_mk_dense_array(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 17632 val_t a = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17633 #ifdef V7_ENABLE_DENSE_ARRAYS
Marko Mikulicic 0:c0ecb8bf28eb 17634 v7_own(v7, &a);
Marko Mikulicic 0:c0ecb8bf28eb 17635 v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17636
Marko Mikulicic 0:c0ecb8bf28eb 17637 /*
Marko Mikulicic 0:c0ecb8bf28eb 17638 * Before setting a `V7_OBJ_DENSE_ARRAY` flag, make sure we don't have
Marko Mikulicic 0:c0ecb8bf28eb 17639 * `V7_OBJ_FUNCTION` flag set
Marko Mikulicic 0:c0ecb8bf28eb 17640 */
Marko Mikulicic 0:c0ecb8bf28eb 17641 assert(!(get_object_struct(a)->attributes & V7_OBJ_FUNCTION));
Marko Mikulicic 0:c0ecb8bf28eb 17642 get_object_struct(a)->attributes |= V7_OBJ_DENSE_ARRAY;
Marko Mikulicic 0:c0ecb8bf28eb 17643
Marko Mikulicic 0:c0ecb8bf28eb 17644 v7_disown(v7, &a);
Marko Mikulicic 0:c0ecb8bf28eb 17645 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17646 return a;
Marko Mikulicic 0:c0ecb8bf28eb 17647 }
Marko Mikulicic 0:c0ecb8bf28eb 17648
Marko Mikulicic 0:c0ecb8bf28eb 17649 /* TODO_V7_ERR */
Marko Mikulicic 0:c0ecb8bf28eb 17650 val_t v7_array_get(struct v7 *v7, val_t arr, unsigned long index) {
Marko Mikulicic 0:c0ecb8bf28eb 17651 return v7_array_get2(v7, arr, index, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17652 }
Marko Mikulicic 0:c0ecb8bf28eb 17653
Marko Mikulicic 0:c0ecb8bf28eb 17654 /* TODO_V7_ERR */
Marko Mikulicic 0:c0ecb8bf28eb 17655 val_t v7_array_get2(struct v7 *v7, val_t arr, unsigned long index, int *has) {
Marko Mikulicic 0:c0ecb8bf28eb 17656 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17657 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 17658
Marko Mikulicic 0:c0ecb8bf28eb 17659 if (has != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17660 *has = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17661 }
Marko Mikulicic 0:c0ecb8bf28eb 17662 if (v7_is_object(arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 17663 if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17664 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 17665 v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17666 struct mbuf *abuf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17667 unsigned long len;
Marko Mikulicic 0:c0ecb8bf28eb 17668 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17669 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 17670 }
Marko Mikulicic 0:c0ecb8bf28eb 17671 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17672 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17673 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17674 }
Marko Mikulicic 0:c0ecb8bf28eb 17675 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17676 if (index >= len) {
Marko Mikulicic 0:c0ecb8bf28eb 17677 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17678 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17679 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17680 memcpy(&res, abuf->buf + index * sizeof(val_t), sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17681 if (has != NULL && res != V7_TAG_NOVALUE) *has = 1;
Marko Mikulicic 0:c0ecb8bf28eb 17682 if (res == V7_TAG_NOVALUE) {
Marko Mikulicic 0:c0ecb8bf28eb 17683 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17684 }
Marko Mikulicic 0:c0ecb8bf28eb 17685 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17686 }
Marko Mikulicic 0:c0ecb8bf28eb 17687 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17688 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 17689 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17690 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17691 p = v7_get_property(v7, arr, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 17692 if (has != NULL && p != NULL) *has = 1;
Marko Mikulicic 0:c0ecb8bf28eb 17693 V7_TRY(v7_property_value(v7, arr, p, &res));
Marko Mikulicic 0:c0ecb8bf28eb 17694 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17695 }
Marko Mikulicic 0:c0ecb8bf28eb 17696 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17697 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17698 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17699 }
Marko Mikulicic 0:c0ecb8bf28eb 17700
Marko Mikulicic 0:c0ecb8bf28eb 17701 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17702 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17703 return res;
Marko Mikulicic 0:c0ecb8bf28eb 17704 }
Marko Mikulicic 0:c0ecb8bf28eb 17705
Marko Mikulicic 0:c0ecb8bf28eb 17706 #if V7_ENABLE_DENSE_ARRAYS
Marko Mikulicic 0:c0ecb8bf28eb 17707
Marko Mikulicic 0:c0ecb8bf28eb 17708 /* Create V7 strings for integers such as array indices */
Marko Mikulicic 0:c0ecb8bf28eb 17709 static val_t ulong_to_str(struct v7 *v7, unsigned long n) {
Marko Mikulicic 0:c0ecb8bf28eb 17710 char buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 17711 int len;
Marko Mikulicic 0:c0ecb8bf28eb 17712 len = c_snprintf(buf, sizeof(buf), "%lu", n);
Marko Mikulicic 0:c0ecb8bf28eb 17713 return v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 17714 }
Marko Mikulicic 0:c0ecb8bf28eb 17715
Marko Mikulicic 0:c0ecb8bf28eb 17716 /*
Marko Mikulicic 0:c0ecb8bf28eb 17717 * Pack 15-bit length and 15 bit index, leaving 2 bits for tag. the LSB has to
Marko Mikulicic 0:c0ecb8bf28eb 17718 * be set to distinguish it from a prop pointer.
Marko Mikulicic 0:c0ecb8bf28eb 17719 * In alternative we just fetch the length from obj at each call to v7_next_prop
Marko Mikulicic 0:c0ecb8bf28eb 17720 * and just stuff the index here (e.g. on 8/16-bit platforms).
Marko Mikulicic 0:c0ecb8bf28eb 17721 * TODO(mkm): conditional for 16-bit platforms
Marko Mikulicic 0:c0ecb8bf28eb 17722 */
Marko Mikulicic 0:c0ecb8bf28eb 17723 #define PACK_ITER(len, idx) \
Marko Mikulicic 0:c0ecb8bf28eb 17724 ((struct v7_property *) ((len) << 17 | (idx) << 1 | 1))
Marko Mikulicic 0:c0ecb8bf28eb 17725
Marko Mikulicic 0:c0ecb8bf28eb 17726 #define UNPACK_ITER_LEN(p) (((uintptr_t) p) >> 17)
Marko Mikulicic 0:c0ecb8bf28eb 17727 #define UNPACK_ITER_IDX(p) ((((uintptr_t) p) >> 1) & 0x7FFF)
Marko Mikulicic 0:c0ecb8bf28eb 17728 #define IS_PACKED_ITER(p) ((uintptr_t) p & 1)
Marko Mikulicic 0:c0ecb8bf28eb 17729
Marko Mikulicic 0:c0ecb8bf28eb 17730 void *v7_next_prop(struct v7 *v7, val_t obj, void *h, val_t *name, val_t *val,
Marko Mikulicic 0:c0ecb8bf28eb 17731 v7_prop_attr_t *attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 17732 struct v7_property *p = (struct v7_property *) h;
Marko Mikulicic 0:c0ecb8bf28eb 17733
Marko Mikulicic 0:c0ecb8bf28eb 17734 if (get_object_struct(obj)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17735 /* This is a dense array. Find backing mbuf and fetch values from there */
Marko Mikulicic 0:c0ecb8bf28eb 17736 struct v7_property *hp =
Marko Mikulicic 0:c0ecb8bf28eb 17737 v7_get_own_property2(v7, obj, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17738 struct mbuf *abuf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17739 unsigned long len, idx;
Marko Mikulicic 0:c0ecb8bf28eb 17740 if (hp != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17741 abuf = (struct mbuf *) v7_get_ptr(v7, hp->value);
Marko Mikulicic 0:c0ecb8bf28eb 17742 }
Marko Mikulicic 0:c0ecb8bf28eb 17743 if (abuf == NULL) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17744 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17745 if (len == 0) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17746 idx = (p == NULL) ? 0 : UNPACK_ITER_IDX(p) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17747 p = (idx == len) ? get_object_struct(obj)->properties : PACK_ITER(len, idx);
Marko Mikulicic 0:c0ecb8bf28eb 17748 if (val != NULL) *val = ((val_t *) abuf->buf)[idx];
Marko Mikulicic 0:c0ecb8bf28eb 17749 if (attrs != NULL) *attrs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17750 if (name != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17751 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17752 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17753 *name = v7_mk_string(v7, buf, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 17754 }
Marko Mikulicic 0:c0ecb8bf28eb 17755 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17756 /* Ordinary object */
Marko Mikulicic 0:c0ecb8bf28eb 17757 p = (p == NULL) ? get_object_struct(obj)->properties : p->next;
Marko Mikulicic 0:c0ecb8bf28eb 17758 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17759 if (name != NULL) *name = p->name;
Marko Mikulicic 0:c0ecb8bf28eb 17760 if (val != NULL) *val = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 17761 if (attrs != NULL) *attrs = p->attributes;
Marko Mikulicic 0:c0ecb8bf28eb 17762 }
Marko Mikulicic 0:c0ecb8bf28eb 17763 }
Marko Mikulicic 0:c0ecb8bf28eb 17764
Marko Mikulicic 0:c0ecb8bf28eb 17765 return p;
Marko Mikulicic 0:c0ecb8bf28eb 17766 }
Marko Mikulicic 0:c0ecb8bf28eb 17767
Marko Mikulicic 0:c0ecb8bf28eb 17768 V7_PRIVATE val_t
Marko Mikulicic 0:c0ecb8bf28eb 17769 v7_iter_get_value(struct v7 *v7, val_t obj, struct v7_property *p) {
Marko Mikulicic 0:c0ecb8bf28eb 17770 return IS_PACKED_ITER(p) ? v7_array_get(v7, obj, UNPACK_ITER_IDX(p))
Marko Mikulicic 0:c0ecb8bf28eb 17771 : p->value;
Marko Mikulicic 0:c0ecb8bf28eb 17772 }
Marko Mikulicic 0:c0ecb8bf28eb 17773
Marko Mikulicic 0:c0ecb8bf28eb 17774 V7_PRIVATE val_t v7_iter_get_name(struct v7 *v7, struct v7_property *p) {
Marko Mikulicic 0:c0ecb8bf28eb 17775 return IS_PACKED_ITER(p) ? ulong_to_str(v7, UNPACK_ITER_IDX(p)) : p->name;
Marko Mikulicic 0:c0ecb8bf28eb 17776 }
Marko Mikulicic 0:c0ecb8bf28eb 17777
Marko Mikulicic 0:c0ecb8bf28eb 17778 V7_PRIVATE uint8_t v7_iter_get_attrs(struct v7_property *p) {
Marko Mikulicic 0:c0ecb8bf28eb 17779 return IS_PACKED_ITER(p) ? 0 : p->attributes;
Marko Mikulicic 0:c0ecb8bf28eb 17780 }
Marko Mikulicic 0:c0ecb8bf28eb 17781
Marko Mikulicic 0:c0ecb8bf28eb 17782 /* return array index as number or undefined. works with iterators */
Marko Mikulicic 0:c0ecb8bf28eb 17783 V7_PRIVATE enum v7_err v7_iter_get_index(struct v7 *v7, struct v7_property *p,
Marko Mikulicic 0:c0ecb8bf28eb 17784 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17785 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17786 int ok;
Marko Mikulicic 0:c0ecb8bf28eb 17787 unsigned long res;
Marko Mikulicic 0:c0ecb8bf28eb 17788 if (IS_PACKED_ITER(p)) {
Marko Mikulicic 0:c0ecb8bf28eb 17789 *res = v7_mk_number(v7, UNPACK_ITER_IDX(p));
Marko Mikulicic 0:c0ecb8bf28eb 17790 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17791 }
Marko Mikulicic 0:c0ecb8bf28eb 17792 V7_TRY(str_to_ulong(v7, p->name, &ok, &res));
Marko Mikulicic 0:c0ecb8bf28eb 17793 if (!ok || res >= UINT32_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 17794 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17795 }
Marko Mikulicic 0:c0ecb8bf28eb 17796 *res = v7_mk_number(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 17797 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17798
Marko Mikulicic 0:c0ecb8bf28eb 17799 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17800 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17801 }
Marko Mikulicic 0:c0ecb8bf28eb 17802 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17803
Marko Mikulicic 0:c0ecb8bf28eb 17804 /* TODO_V7_ERR */
Marko Mikulicic 0:c0ecb8bf28eb 17805 unsigned long v7_array_length(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17806 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17807 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 17808 unsigned long len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17809
Marko Mikulicic 0:c0ecb8bf28eb 17810 if (!v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 17811 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17812 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17813 }
Marko Mikulicic 0:c0ecb8bf28eb 17814
Marko Mikulicic 0:c0ecb8bf28eb 17815 #if V7_ENABLE_DENSE_ARRAYS
Marko Mikulicic 0:c0ecb8bf28eb 17816 if (get_object_struct(v)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17817 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 17818 v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17819 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 17820 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17821 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17822 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17823 }
Marko Mikulicic 0:c0ecb8bf28eb 17824 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 17825 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17826 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17827 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17828 }
Marko Mikulicic 0:c0ecb8bf28eb 17829 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17830 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17831 }
Marko Mikulicic 0:c0ecb8bf28eb 17832 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17833
Marko Mikulicic 0:c0ecb8bf28eb 17834 for (p = get_object_struct(v)->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 17835 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17836 unsigned long n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17837 V7_TRY(str_to_ulong(v7, p->name, &ok, &n));
Marko Mikulicic 0:c0ecb8bf28eb 17838 if (ok && n >= len && n < UINT32_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 17839 len = n + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17840 }
Marko Mikulicic 0:c0ecb8bf28eb 17841 }
Marko Mikulicic 0:c0ecb8bf28eb 17842
Marko Mikulicic 0:c0ecb8bf28eb 17843 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17844 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17845 return len;
Marko Mikulicic 0:c0ecb8bf28eb 17846 }
Marko Mikulicic 0:c0ecb8bf28eb 17847
Marko Mikulicic 0:c0ecb8bf28eb 17848 int v7_array_set(struct v7 *v7, val_t arr, unsigned long index, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17849 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17850 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17851 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 17852 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 17853
Marko Mikulicic 0:c0ecb8bf28eb 17854 rcode = v7_array_set_throwing(v7, arr, index, v, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 17855 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 17856 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17857 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 17858 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 17859 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17860 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17861 }
Marko Mikulicic 0:c0ecb8bf28eb 17862 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 17863 }
Marko Mikulicic 0:c0ecb8bf28eb 17864
Marko Mikulicic 0:c0ecb8bf28eb 17865 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 17866 }
Marko Mikulicic 0:c0ecb8bf28eb 17867
Marko Mikulicic 0:c0ecb8bf28eb 17868 enum v7_err v7_array_set_throwing(struct v7 *v7, val_t arr, unsigned long index,
Marko Mikulicic 0:c0ecb8bf28eb 17869 val_t v, int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17870 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17871 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 17872
Marko Mikulicic 0:c0ecb8bf28eb 17873 if (v7_is_object(arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 17874 if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17875 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 17876 v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17877 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 17878 unsigned long len;
Marko Mikulicic 0:c0ecb8bf28eb 17879 assert(p != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17880 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 17881
Marko Mikulicic 0:c0ecb8bf28eb 17882 if (get_object_struct(arr)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
Marko Mikulicic 0:c0ecb8bf28eb 17883 if (is_strict_mode(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 17884 rcode = v7_throwf(v7, TYPE_ERROR, "Object is not extensible");
Marko Mikulicic 0:c0ecb8bf28eb 17885 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17886 }
Marko Mikulicic 0:c0ecb8bf28eb 17887
Marko Mikulicic 0:c0ecb8bf28eb 17888 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17889 }
Marko Mikulicic 0:c0ecb8bf28eb 17890
Marko Mikulicic 0:c0ecb8bf28eb 17891 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17892 abuf = (struct mbuf *) malloc(sizeof(*abuf));
Marko Mikulicic 0:c0ecb8bf28eb 17893 mbuf_init(abuf, sizeof(val_t) * (index + 1));
Marko Mikulicic 0:c0ecb8bf28eb 17894 p->value = v7_mk_foreign(v7, abuf);
Marko Mikulicic 0:c0ecb8bf28eb 17895 }
Marko Mikulicic 0:c0ecb8bf28eb 17896 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17897 /* TODO(mkm): possibly promote to sparse array */
Marko Mikulicic 0:c0ecb8bf28eb 17898 if (index > len) {
Marko Mikulicic 0:c0ecb8bf28eb 17899 unsigned long i;
Marko Mikulicic 0:c0ecb8bf28eb 17900 val_t s = V7_TAG_NOVALUE;
Marko Mikulicic 0:c0ecb8bf28eb 17901 for (i = len; i < index; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 17902 mbuf_append(abuf, (char *) &s, sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17903 }
Marko Mikulicic 0:c0ecb8bf28eb 17904 len = index;
Marko Mikulicic 0:c0ecb8bf28eb 17905 }
Marko Mikulicic 0:c0ecb8bf28eb 17906
Marko Mikulicic 0:c0ecb8bf28eb 17907 if (index == len) {
Marko Mikulicic 0:c0ecb8bf28eb 17908 mbuf_append(abuf, (char *) &v, sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17909 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17910 memcpy(abuf->buf + index * sizeof(val_t), &v, sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17911 }
Marko Mikulicic 0:c0ecb8bf28eb 17912 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17913 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17914 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17915 {
Marko Mikulicic 0:c0ecb8bf28eb 17916 struct v7_property *tmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17917 rcode = set_property(v7, arr, buf, n, v, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 17918 ires = (tmp == NULL) ? -1 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 17919 }
Marko Mikulicic 0:c0ecb8bf28eb 17920 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 17921 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17922 }
Marko Mikulicic 0:c0ecb8bf28eb 17923 }
Marko Mikulicic 0:c0ecb8bf28eb 17924 }
Marko Mikulicic 0:c0ecb8bf28eb 17925
Marko Mikulicic 0:c0ecb8bf28eb 17926 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17927 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17928 *res = ires;
Marko Mikulicic 0:c0ecb8bf28eb 17929 }
Marko Mikulicic 0:c0ecb8bf28eb 17930 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17931 }
Marko Mikulicic 0:c0ecb8bf28eb 17932
Marko Mikulicic 0:c0ecb8bf28eb 17933 void v7_array_del(struct v7 *v7, val_t arr, unsigned long index) {
Marko Mikulicic 0:c0ecb8bf28eb 17934 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17935 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17936 v7_del(v7, arr, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 17937 }
Marko Mikulicic 0:c0ecb8bf28eb 17938
Marko Mikulicic 0:c0ecb8bf28eb 17939 int v7_array_push(struct v7 *v7, v7_val_t arr, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17940 return v7_array_set(v7, arr, v7_array_length(v7, arr), v);
Marko Mikulicic 0:c0ecb8bf28eb 17941 }
Marko Mikulicic 0:c0ecb8bf28eb 17942
Marko Mikulicic 0:c0ecb8bf28eb 17943 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 17944 enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v,
Marko Mikulicic 0:c0ecb8bf28eb 17945 int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17946 return v7_array_set_throwing(v7, arr, v7_array_length(v7, arr), v, res);
Marko Mikulicic 0:c0ecb8bf28eb 17947 }
Marko Mikulicic 0:c0ecb8bf28eb 17948 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 17949 #line 1 "v7/src/object.c"
Marko Mikulicic 0:c0ecb8bf28eb 17950 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17951 /*
Marko Mikulicic 0:c0ecb8bf28eb 17952 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 17953 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 17954 */
Marko Mikulicic 0:c0ecb8bf28eb 17955
Marko Mikulicic 0:c0ecb8bf28eb 17956 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17957 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17958 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17959 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17960 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17961 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17962 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17963 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17964 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17965 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17966 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17967 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17968 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17969
Marko Mikulicic 0:c0ecb8bf28eb 17970 /*
Marko Mikulicic 0:c0ecb8bf28eb 17971 * Default property attributes (see `v7_prop_attr_t`)
Marko Mikulicic 0:c0ecb8bf28eb 17972 */
Marko Mikulicic 0:c0ecb8bf28eb 17973 #define V7_DEFAULT_PROPERTY_ATTRS 0
Marko Mikulicic 0:c0ecb8bf28eb 17974
Marko Mikulicic 0:c0ecb8bf28eb 17975 V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 17976 struct v7_generic_object *o = new_generic_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17977 if (o == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17978 return V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17979 }
Marko Mikulicic 0:c0ecb8bf28eb 17980 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 17981 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 17982 o->base.entity_id_base = V7_ENTITY_ID_PART_OBJ;
Marko Mikulicic 0:c0ecb8bf28eb 17983 o->base.entity_id_spec = V7_ENTITY_ID_PART_GEN_OBJ;
Marko Mikulicic 0:c0ecb8bf28eb 17984 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17985 o->base.properties = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17986 obj_prototype_set(v7, &o->base, get_object_struct(prototype));
Marko Mikulicic 0:c0ecb8bf28eb 17987 return v7_object_to_value(&o->base);
Marko Mikulicic 0:c0ecb8bf28eb 17988 }
Marko Mikulicic 0:c0ecb8bf28eb 17989
Marko Mikulicic 0:c0ecb8bf28eb 17990 v7_val_t v7_mk_object(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 17991 return mk_object(v7, v7->vals.object_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 17992 }
Marko Mikulicic 0:c0ecb8bf28eb 17993
Marko Mikulicic 0:c0ecb8bf28eb 17994 V7_PRIVATE val_t v7_object_to_value(struct v7_object *o) {
Marko Mikulicic 0:c0ecb8bf28eb 17995 if (o == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17996 return V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17997 } else if (o->attributes & V7_OBJ_FUNCTION) {
Marko Mikulicic 0:c0ecb8bf28eb 17998 return pointer_to_value(o) | V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 17999 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18000 return pointer_to_value(o) | V7_TAG_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 18001 }
Marko Mikulicic 0:c0ecb8bf28eb 18002 }
Marko Mikulicic 0:c0ecb8bf28eb 18003
Marko Mikulicic 0:c0ecb8bf28eb 18004 V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 18005 struct v7_generic_object *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18006 if (v7_is_null(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18007 ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18008 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18009 assert(v7_is_generic_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 18010 ret = (struct v7_generic_object *) get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 18011 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18012 if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 18013 fprintf(stderr, "not a generic object!\n");
Marko Mikulicic 0:c0ecb8bf28eb 18014 abort();
Marko Mikulicic 0:c0ecb8bf28eb 18015 } else if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_GEN_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 18016 fprintf(stderr, "not an object (but is a generic object)!\n");
Marko Mikulicic 0:c0ecb8bf28eb 18017 abort();
Marko Mikulicic 0:c0ecb8bf28eb 18018 }
Marko Mikulicic 0:c0ecb8bf28eb 18019 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18020 }
Marko Mikulicic 0:c0ecb8bf28eb 18021 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18022 }
Marko Mikulicic 0:c0ecb8bf28eb 18023
Marko Mikulicic 0:c0ecb8bf28eb 18024 V7_PRIVATE struct v7_object *get_object_struct(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 18025 struct v7_object *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18026 if (v7_is_null(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18027 ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18028 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18029 assert(v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 18030 ret = (struct v7_object *) get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 18031 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18032 if (ret->entity_id_base != V7_ENTITY_ID_PART_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 18033 fprintf(stderr, "not an object!\n");
Marko Mikulicic 0:c0ecb8bf28eb 18034 abort();
Marko Mikulicic 0:c0ecb8bf28eb 18035 }
Marko Mikulicic 0:c0ecb8bf28eb 18036 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18037 }
Marko Mikulicic 0:c0ecb8bf28eb 18038 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18039 }
Marko Mikulicic 0:c0ecb8bf28eb 18040
Marko Mikulicic 0:c0ecb8bf28eb 18041 int v7_is_object(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 18042 return (v & V7_TAG_MASK) == V7_TAG_OBJECT ||
Marko Mikulicic 0:c0ecb8bf28eb 18043 (v & V7_TAG_MASK) == V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 18044 }
Marko Mikulicic 0:c0ecb8bf28eb 18045
Marko Mikulicic 0:c0ecb8bf28eb 18046 V7_PRIVATE int v7_is_generic_object(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 18047 return (v & V7_TAG_MASK) == V7_TAG_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 18048 }
Marko Mikulicic 0:c0ecb8bf28eb 18049
Marko Mikulicic 0:c0ecb8bf28eb 18050 /* Object properties {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 18051
Marko Mikulicic 0:c0ecb8bf28eb 18052 V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 18053 struct v7_property *p = new_property(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18054 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18055 p->entity_id = V7_ENTITY_ID_PROP;
Marko Mikulicic 0:c0ecb8bf28eb 18056 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18057 p->next = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18058 p->name = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18059 p->value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18060 p->attributes = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18061 return p;
Marko Mikulicic 0:c0ecb8bf28eb 18062 }
Marko Mikulicic 0:c0ecb8bf28eb 18063
Marko Mikulicic 0:c0ecb8bf28eb 18064 V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18065 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18066 size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 18067 v7_prop_attr_t attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 18068 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 18069 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 18070 val_t ss;
Marko Mikulicic 0:c0ecb8bf28eb 18071 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18072 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18073 }
Marko Mikulicic 0:c0ecb8bf28eb 18074 if (len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18075 len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18076 }
Marko Mikulicic 0:c0ecb8bf28eb 18077
Marko Mikulicic 0:c0ecb8bf28eb 18078 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 18079 /*
Marko Mikulicic 0:c0ecb8bf28eb 18080 * len check is needed to allow getting the mbuf from the hidden property.
Marko Mikulicic 0:c0ecb8bf28eb 18081 * TODO(mkm): however hidden properties cannot be safely represented with
Marko Mikulicic 0:c0ecb8bf28eb 18082 * a zero length string anyway, so this will change.
Marko Mikulicic 0:c0ecb8bf28eb 18083 */
Marko Mikulicic 0:c0ecb8bf28eb 18084 if (o->attributes & V7_OBJ_DENSE_ARRAY && len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 18085 int ok, has;
Marko Mikulicic 0:c0ecb8bf28eb 18086 unsigned long i = cstr_to_ulong(name, len, &ok);
Marko Mikulicic 0:c0ecb8bf28eb 18087 if (ok) {
Marko Mikulicic 0:c0ecb8bf28eb 18088 v7->cur_dense_prop->value = v7_array_get2(v7, obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 18089 return has ? v7->cur_dense_prop : NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18090 }
Marko Mikulicic 0:c0ecb8bf28eb 18091 }
Marko Mikulicic 0:c0ecb8bf28eb 18092
Marko Mikulicic 0:c0ecb8bf28eb 18093 if (len <= 5) {
Marko Mikulicic 0:c0ecb8bf28eb 18094 ss = v7_mk_string(v7, name, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18095 for (p = o->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 18096 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18097 if (p->entity_id != V7_ENTITY_ID_PROP) {
Marko Mikulicic 0:c0ecb8bf28eb 18098 fprintf(stderr, "not a prop!=0x%x\n", p->entity_id);
Marko Mikulicic 0:c0ecb8bf28eb 18099 abort();
Marko Mikulicic 0:c0ecb8bf28eb 18100 }
Marko Mikulicic 0:c0ecb8bf28eb 18101 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18102 if (p->name == ss && (attrs == 0 || (p->attributes & attrs))) {
Marko Mikulicic 0:c0ecb8bf28eb 18103 return p;
Marko Mikulicic 0:c0ecb8bf28eb 18104 }
Marko Mikulicic 0:c0ecb8bf28eb 18105 }
Marko Mikulicic 0:c0ecb8bf28eb 18106 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18107 for (p = o->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 18108 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 18109 const char *s = v7_get_string(v7, &p->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 18110 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18111 if (p->entity_id != V7_ENTITY_ID_PROP) {
Marko Mikulicic 0:c0ecb8bf28eb 18112 fprintf(stderr, "not a prop!=0x%x\n", p->entity_id);
Marko Mikulicic 0:c0ecb8bf28eb 18113 abort();
Marko Mikulicic 0:c0ecb8bf28eb 18114 }
Marko Mikulicic 0:c0ecb8bf28eb 18115 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18116 if (n == len && strncmp(s, name, len) == 0 &&
Marko Mikulicic 0:c0ecb8bf28eb 18117 (attrs == 0 || (p->attributes & attrs))) {
Marko Mikulicic 0:c0ecb8bf28eb 18118 return p;
Marko Mikulicic 0:c0ecb8bf28eb 18119 }
Marko Mikulicic 0:c0ecb8bf28eb 18120 }
Marko Mikulicic 0:c0ecb8bf28eb 18121 }
Marko Mikulicic 0:c0ecb8bf28eb 18122 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18123 }
Marko Mikulicic 0:c0ecb8bf28eb 18124
Marko Mikulicic 0:c0ecb8bf28eb 18125 V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18126 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18127 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 18128 return v7_get_own_property2(v7, obj, name, len, 0);
Marko Mikulicic 0:c0ecb8bf28eb 18129 }
Marko Mikulicic 0:c0ecb8bf28eb 18130
Marko Mikulicic 0:c0ecb8bf28eb 18131 V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18132 const char *name, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 18133 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18134 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18135 }
Marko Mikulicic 0:c0ecb8bf28eb 18136 for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18137 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 18138 if ((prop = v7_get_own_property(v7, obj, name, len)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18139 return prop;
Marko Mikulicic 0:c0ecb8bf28eb 18140 }
Marko Mikulicic 0:c0ecb8bf28eb 18141 }
Marko Mikulicic 0:c0ecb8bf28eb 18142 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18143 }
Marko Mikulicic 0:c0ecb8bf28eb 18144
Marko Mikulicic 0:c0ecb8bf28eb 18145 V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18146 v7_val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18147 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18148 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18149 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 18150 STATIC char buf[8];
Marko Mikulicic 0:c0ecb8bf28eb 18151 const char *s = buf;
Marko Mikulicic 0:c0ecb8bf28eb 18152 uint8_t fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18153
Marko Mikulicic 0:c0ecb8bf28eb 18154 if (v7_is_string(name)) {
Marko Mikulicic 0:c0ecb8bf28eb 18155 s = v7_get_string(v7, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18156 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18157 char *stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18158 V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf),
Marko Mikulicic 0:c0ecb8bf28eb 18159 V7_STRINGIFY_DEFAULT, &stmp));
Marko Mikulicic 0:c0ecb8bf28eb 18160 s = stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18161 if (s != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 18162 fr = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18163 }
Marko Mikulicic 0:c0ecb8bf28eb 18164 name_len = strlen(s);
Marko Mikulicic 0:c0ecb8bf28eb 18165 }
Marko Mikulicic 0:c0ecb8bf28eb 18166
Marko Mikulicic 0:c0ecb8bf28eb 18167 *res = v7_get_property(v7, obj, s, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18168
Marko Mikulicic 0:c0ecb8bf28eb 18169 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18170 if (fr) {
Marko Mikulicic 0:c0ecb8bf28eb 18171 free((void *) s);
Marko Mikulicic 0:c0ecb8bf28eb 18172 }
Marko Mikulicic 0:c0ecb8bf28eb 18173 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18174 }
Marko Mikulicic 0:c0ecb8bf28eb 18175
Marko Mikulicic 0:c0ecb8bf28eb 18176 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18177 enum v7_err v7_get_throwing(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18178 size_t name_len, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 18179 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18180 val_t v = obj;
Marko Mikulicic 0:c0ecb8bf28eb 18181
Marko Mikulicic 0:c0ecb8bf28eb 18182 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 18183
Marko Mikulicic 0:c0ecb8bf28eb 18184 if (name_len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18185 name_len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18186 }
Marko Mikulicic 0:c0ecb8bf28eb 18187
Marko Mikulicic 0:c0ecb8bf28eb 18188 if (v7_is_string(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18189 v = v7->vals.string_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18190 } else if (v7_is_number(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18191 v = v7->vals.number_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18192 } else if (v7_is_boolean(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18193 v = v7->vals.boolean_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18194 } else if (v7_is_undefined(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18195 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 18196 v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of undefined",
Marko Mikulicic 0:c0ecb8bf28eb 18197 (int) name_len, name);
Marko Mikulicic 0:c0ecb8bf28eb 18198 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18199 } else if (v7_is_null(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18200 rcode = v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of null",
Marko Mikulicic 0:c0ecb8bf28eb 18201 (int) name_len, name);
Marko Mikulicic 0:c0ecb8bf28eb 18202 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18203 } else if (is_cfunction_lite(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18204 v = v7->vals.function_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18205 }
Marko Mikulicic 0:c0ecb8bf28eb 18206
Marko Mikulicic 0:c0ecb8bf28eb 18207 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18208 {
Marko Mikulicic 0:c0ecb8bf28eb 18209 struct v7_object *o = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18210 if (v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18211 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 18212 }
Marko Mikulicic 0:c0ecb8bf28eb 18213
Marko Mikulicic 0:c0ecb8bf28eb 18214 if (o != NULL && (o->attributes & V7_OBJ_PROXY) &&
Marko Mikulicic 0:c0ecb8bf28eb 18215 !is_special_proxy_name(name, name_len)) {
Marko Mikulicic 0:c0ecb8bf28eb 18216 /* we need to access the target object through a proxy */
Marko Mikulicic 0:c0ecb8bf28eb 18217
Marko Mikulicic 0:c0ecb8bf28eb 18218 val_t target_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18219 val_t handler_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18220 val_t name_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18221 val_t get_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18222 val_t get_args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18223
Marko Mikulicic 0:c0ecb8bf28eb 18224 /*
Marko Mikulicic 0:c0ecb8bf28eb 18225 * we need to create a copy of the name, because the given `name` might
Marko Mikulicic 0:c0ecb8bf28eb 18226 * be returned by v7_get_string(), and any object creation might
Marko Mikulicic 0:c0ecb8bf28eb 18227 * invalidate this pointer. Below, we're going to create some objects.
Marko Mikulicic 0:c0ecb8bf28eb 18228 *
Marko Mikulicic 0:c0ecb8bf28eb 18229 * It would probably be cleaner to always create a copy before calling
Marko Mikulicic 0:c0ecb8bf28eb 18230 * v7_get_throwing if the name was returned by v7_get_string(), but that
Marko Mikulicic 0:c0ecb8bf28eb 18231 * would cause additional pressure on the heap, so let's not do that
Marko Mikulicic 0:c0ecb8bf28eb 18232 */
Marko Mikulicic 0:c0ecb8bf28eb 18233 char *name_copy = (char *) calloc(1, name_len + 1 /* null-term */);
Marko Mikulicic 0:c0ecb8bf28eb 18234 memcpy(name_copy, name, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18235
Marko Mikulicic 0:c0ecb8bf28eb 18236 v7_own(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18237 v7_own(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18238 v7_own(v7, &name_v);
Marko Mikulicic 0:c0ecb8bf28eb 18239 v7_own(v7, &get_v);
Marko Mikulicic 0:c0ecb8bf28eb 18240 v7_own(v7, &get_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18241
Marko Mikulicic 0:c0ecb8bf28eb 18242 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v),
Marko Mikulicic 0:c0ecb8bf28eb 18243 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18244 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v),
Marko Mikulicic 0:c0ecb8bf28eb 18245 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18246 V7_TRY2(v7_get_throwing(v7, handler_v, "get", ~0, &get_v), clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18247
Marko Mikulicic 0:c0ecb8bf28eb 18248 if (v7_is_callable(v7, get_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18249 /* The `get` callback is actually callable, so, use it */
Marko Mikulicic 0:c0ecb8bf28eb 18250
Marko Mikulicic 0:c0ecb8bf28eb 18251 /* prepare arguments for the callback */
Marko Mikulicic 0:c0ecb8bf28eb 18252 get_args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18253 /*
Marko Mikulicic 0:c0ecb8bf28eb 18254 * TODO(dfrank): don't copy string in case we already have val_t (we
Marko Mikulicic 0:c0ecb8bf28eb 18255 * need some generic function which will take both `const char *` and
Marko Mikulicic 0:c0ecb8bf28eb 18256 * val_t)
Marko Mikulicic 0:c0ecb8bf28eb 18257 */
Marko Mikulicic 0:c0ecb8bf28eb 18258 v7_array_set(v7, get_args_v, 0, target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18259 v7_array_set(v7, get_args_v, 1,
Marko Mikulicic 0:c0ecb8bf28eb 18260 v7_mk_string(v7, name_copy, name_len, 1));
Marko Mikulicic 0:c0ecb8bf28eb 18261
Marko Mikulicic 0:c0ecb8bf28eb 18262 /* call `get` callback */
Marko Mikulicic 0:c0ecb8bf28eb 18263 V7_TRY2(b_apply(v7, get_v, V7_UNDEFINED, get_args_v, 0, res),
Marko Mikulicic 0:c0ecb8bf28eb 18264 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18265 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18266 /*
Marko Mikulicic 0:c0ecb8bf28eb 18267 * there's no `get` callback: then, get property from the target object
Marko Mikulicic 0:c0ecb8bf28eb 18268 * (not from the proxy object)
Marko Mikulicic 0:c0ecb8bf28eb 18269 */
Marko Mikulicic 0:c0ecb8bf28eb 18270 V7_TRY2(v7_get_throwing(v7, target_v, name_copy, name_len, res),
Marko Mikulicic 0:c0ecb8bf28eb 18271 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18272 }
Marko Mikulicic 0:c0ecb8bf28eb 18273
Marko Mikulicic 0:c0ecb8bf28eb 18274 clean_proxy:
Marko Mikulicic 0:c0ecb8bf28eb 18275
Marko Mikulicic 0:c0ecb8bf28eb 18276 free(name_copy);
Marko Mikulicic 0:c0ecb8bf28eb 18277
Marko Mikulicic 0:c0ecb8bf28eb 18278 v7_disown(v7, &get_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18279 v7_disown(v7, &get_v);
Marko Mikulicic 0:c0ecb8bf28eb 18280 v7_disown(v7, &name_v);
Marko Mikulicic 0:c0ecb8bf28eb 18281 v7_disown(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18282 v7_disown(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18283 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18284 }
Marko Mikulicic 0:c0ecb8bf28eb 18285 }
Marko Mikulicic 0:c0ecb8bf28eb 18286 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18287
Marko Mikulicic 0:c0ecb8bf28eb 18288 /* regular (non-proxy) property access */
Marko Mikulicic 0:c0ecb8bf28eb 18289 V7_TRY(
Marko Mikulicic 0:c0ecb8bf28eb 18290 v7_property_value(v7, obj, v7_get_property(v7, v, name, name_len), res));
Marko Mikulicic 0:c0ecb8bf28eb 18291
Marko Mikulicic 0:c0ecb8bf28eb 18292 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18293 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 18294 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18295 }
Marko Mikulicic 0:c0ecb8bf28eb 18296
Marko Mikulicic 0:c0ecb8bf28eb 18297 v7_val_t v7_get(struct v7 *v7, val_t obj, const char *name, size_t name_len) {
Marko Mikulicic 0:c0ecb8bf28eb 18298 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18299 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18300 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18301 v7_val_t ret = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18302
Marko Mikulicic 0:c0ecb8bf28eb 18303 rcode = v7_get_throwing(v7, obj, name, name_len, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 18304 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18305 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18306 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 18307 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18308 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18309 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18310 }
Marko Mikulicic 0:c0ecb8bf28eb 18311 ret = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18312 }
Marko Mikulicic 0:c0ecb8bf28eb 18313
Marko Mikulicic 0:c0ecb8bf28eb 18314 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18315 }
Marko Mikulicic 0:c0ecb8bf28eb 18316
Marko Mikulicic 0:c0ecb8bf28eb 18317 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18318 V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18319 v7_val_t name, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 18320 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18321 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 18322 STATIC char buf[8];
Marko Mikulicic 0:c0ecb8bf28eb 18323 const char *s = buf;
Marko Mikulicic 0:c0ecb8bf28eb 18324 uint8_t fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18325
Marko Mikulicic 0:c0ecb8bf28eb 18326 /* subscripting strings */
Marko Mikulicic 0:c0ecb8bf28eb 18327 if (v7_is_string(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18328 char ch;
Marko Mikulicic 0:c0ecb8bf28eb 18329 double dch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18330
Marko Mikulicic 0:c0ecb8bf28eb 18331 rcode = v7_char_code_at(v7, obj, name, &dch);
Marko Mikulicic 0:c0ecb8bf28eb 18332 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18333 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18334 }
Marko Mikulicic 0:c0ecb8bf28eb 18335
Marko Mikulicic 0:c0ecb8bf28eb 18336 if (!isnan(dch)) {
Marko Mikulicic 0:c0ecb8bf28eb 18337 ch = dch;
Marko Mikulicic 0:c0ecb8bf28eb 18338 *res = v7_mk_string(v7, &ch, 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18339 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18340 }
Marko Mikulicic 0:c0ecb8bf28eb 18341 }
Marko Mikulicic 0:c0ecb8bf28eb 18342
Marko Mikulicic 0:c0ecb8bf28eb 18343 if (v7_is_string(name)) {
Marko Mikulicic 0:c0ecb8bf28eb 18344 s = v7_get_string(v7, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18345 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18346 char *stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18347 V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf),
Marko Mikulicic 0:c0ecb8bf28eb 18348 V7_STRINGIFY_DEFAULT, &stmp));
Marko Mikulicic 0:c0ecb8bf28eb 18349 s = stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18350 if (s != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 18351 fr = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18352 }
Marko Mikulicic 0:c0ecb8bf28eb 18353 name_len = strlen(s);
Marko Mikulicic 0:c0ecb8bf28eb 18354 }
Marko Mikulicic 0:c0ecb8bf28eb 18355 V7_TRY(v7_get_throwing(v7, obj, s, name_len, res));
Marko Mikulicic 0:c0ecb8bf28eb 18356
Marko Mikulicic 0:c0ecb8bf28eb 18357 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18358 if (fr) {
Marko Mikulicic 0:c0ecb8bf28eb 18359 free((void *) s);
Marko Mikulicic 0:c0ecb8bf28eb 18360 }
Marko Mikulicic 0:c0ecb8bf28eb 18361 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18362 }
Marko Mikulicic 0:c0ecb8bf28eb 18363
Marko Mikulicic 0:c0ecb8bf28eb 18364 V7_PRIVATE void v7_destroy_property(struct v7_property **p) {
Marko Mikulicic 0:c0ecb8bf28eb 18365 *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18366 }
Marko Mikulicic 0:c0ecb8bf28eb 18367
Marko Mikulicic 0:c0ecb8bf28eb 18368 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18369 V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop,
Marko Mikulicic 0:c0ecb8bf28eb 18370 val_t obj, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 18371 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18372 val_t setter = prop->value, args;
Marko Mikulicic 0:c0ecb8bf28eb 18373 v7_own(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18374 args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18375 v7_own(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 18376 if (prop->attributes & V7_PROPERTY_GETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18377 setter = v7_array_get(v7, prop->value, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18378 }
Marko Mikulicic 0:c0ecb8bf28eb 18379 v7_array_set(v7, args, 0, val);
Marko Mikulicic 0:c0ecb8bf28eb 18380 v7_disown(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 18381 v7_disown(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18382 {
Marko Mikulicic 0:c0ecb8bf28eb 18383 val_t val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18384 V7_TRY(b_apply(v7, setter, obj, args, 0, &val));
Marko Mikulicic 0:c0ecb8bf28eb 18385 }
Marko Mikulicic 0:c0ecb8bf28eb 18386
Marko Mikulicic 0:c0ecb8bf28eb 18387 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18388 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18389 }
Marko Mikulicic 0:c0ecb8bf28eb 18390
Marko Mikulicic 0:c0ecb8bf28eb 18391 static v7_prop_attr_t apply_attrs_desc(v7_prop_attr_desc_t attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 18392 v7_prop_attr_t old_attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 18393 v7_prop_attr_t ret = old_attrs;
Marko Mikulicic 0:c0ecb8bf28eb 18394 if (old_attrs & V7_PROPERTY_NON_CONFIGURABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18395 /*
Marko Mikulicic 0:c0ecb8bf28eb 18396 * The property is non-configurable: we can only change it from being
Marko Mikulicic 0:c0ecb8bf28eb 18397 * writable to non-writable
Marko Mikulicic 0:c0ecb8bf28eb 18398 */
Marko Mikulicic 0:c0ecb8bf28eb 18399
Marko Mikulicic 0:c0ecb8bf28eb 18400 if ((attrs_desc >> _V7_DESC_SHIFT) & V7_PROPERTY_NON_WRITABLE &&
Marko Mikulicic 0:c0ecb8bf28eb 18401 (attrs_desc & V7_PROPERTY_NON_WRITABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 18402 ret |= V7_PROPERTY_NON_WRITABLE;
Marko Mikulicic 0:c0ecb8bf28eb 18403 }
Marko Mikulicic 0:c0ecb8bf28eb 18404
Marko Mikulicic 0:c0ecb8bf28eb 18405 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18406 /* The property is configurable: we can change any attributes */
Marko Mikulicic 0:c0ecb8bf28eb 18407 ret = (old_attrs & ~(attrs_desc >> _V7_DESC_SHIFT)) |
Marko Mikulicic 0:c0ecb8bf28eb 18408 (attrs_desc & _V7_DESC_MASK);
Marko Mikulicic 0:c0ecb8bf28eb 18409 }
Marko Mikulicic 0:c0ecb8bf28eb 18410
Marko Mikulicic 0:c0ecb8bf28eb 18411 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18412 }
Marko Mikulicic 0:c0ecb8bf28eb 18413
Marko Mikulicic 0:c0ecb8bf28eb 18414 int v7_def(struct v7 *v7, val_t obj, const char *name, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 18415 v7_prop_attr_desc_t attrs_desc, v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 18416 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18417 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18418 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18419 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18420
Marko Mikulicic 0:c0ecb8bf28eb 18421 {
Marko Mikulicic 0:c0ecb8bf28eb 18422 struct v7_property *tmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18423 rcode = def_property(v7, obj, name, len, attrs_desc, val, 0 /*not assign*/,
Marko Mikulicic 0:c0ecb8bf28eb 18424 &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 18425 ret = (tmp == NULL) ? -1 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 18426 }
Marko Mikulicic 0:c0ecb8bf28eb 18427
Marko Mikulicic 0:c0ecb8bf28eb 18428 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18429 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18430 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 18431 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18432 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18433 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18434 }
Marko Mikulicic 0:c0ecb8bf28eb 18435 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18436 }
Marko Mikulicic 0:c0ecb8bf28eb 18437
Marko Mikulicic 0:c0ecb8bf28eb 18438 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18439 }
Marko Mikulicic 0:c0ecb8bf28eb 18440
Marko Mikulicic 0:c0ecb8bf28eb 18441 int v7_set(struct v7 *v7, val_t obj, const char *name, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 18442 v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 18443 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18444 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18445 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18446 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18447
Marko Mikulicic 0:c0ecb8bf28eb 18448 {
Marko Mikulicic 0:c0ecb8bf28eb 18449 struct v7_property *tmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18450 rcode = set_property(v7, obj, name, len, val, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 18451 ret = (tmp == NULL) ? -1 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 18452 }
Marko Mikulicic 0:c0ecb8bf28eb 18453
Marko Mikulicic 0:c0ecb8bf28eb 18454 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18455 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18456 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 18457 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18458 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18459 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18460 }
Marko Mikulicic 0:c0ecb8bf28eb 18461 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18462 }
Marko Mikulicic 0:c0ecb8bf28eb 18463
Marko Mikulicic 0:c0ecb8bf28eb 18464 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18465 }
Marko Mikulicic 0:c0ecb8bf28eb 18466
Marko Mikulicic 0:c0ecb8bf28eb 18467 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18468 V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18469 val_t val, struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18470 return def_property_v(v7, obj, name, 0, val, 1 /*as_assign*/, res);
Marko Mikulicic 0:c0ecb8bf28eb 18471 }
Marko Mikulicic 0:c0ecb8bf28eb 18472
Marko Mikulicic 0:c0ecb8bf28eb 18473 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18474 V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18475 size_t len, v7_val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 18476 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18477 return def_property(v7, obj, name, len, 0, val, 1 /*as_assign*/, res);
Marko Mikulicic 0:c0ecb8bf28eb 18478 }
Marko Mikulicic 0:c0ecb8bf28eb 18479
Marko Mikulicic 0:c0ecb8bf28eb 18480 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18481 V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18482 v7_prop_attr_desc_t attrs_desc, val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 18483 uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 18484 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18485 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18486 struct v7_property *prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18487 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 18488 const char *n = v7_get_string(v7, &name, &len);
Marko Mikulicic 0:c0ecb8bf28eb 18489
Marko Mikulicic 0:c0ecb8bf28eb 18490 v7_own(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 18491 v7_own(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18492
Marko Mikulicic 0:c0ecb8bf28eb 18493 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18494 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18495 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18496 }
Marko Mikulicic 0:c0ecb8bf28eb 18497
Marko Mikulicic 0:c0ecb8bf28eb 18498 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18499 if ((get_object_struct(obj)->attributes & V7_OBJ_PROXY) &&
Marko Mikulicic 0:c0ecb8bf28eb 18500 !is_special_proxy_name(n, len)) {
Marko Mikulicic 0:c0ecb8bf28eb 18501 /* we need to access the target object through a proxy */
Marko Mikulicic 0:c0ecb8bf28eb 18502
Marko Mikulicic 0:c0ecb8bf28eb 18503 val_t target_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18504 val_t handler_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18505 val_t set_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18506 val_t set_args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18507
Marko Mikulicic 0:c0ecb8bf28eb 18508 v7_own(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18509 v7_own(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18510 v7_own(v7, &set_v);
Marko Mikulicic 0:c0ecb8bf28eb 18511 v7_own(v7, &set_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18512
Marko Mikulicic 0:c0ecb8bf28eb 18513 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v),
Marko Mikulicic 0:c0ecb8bf28eb 18514 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18515 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v),
Marko Mikulicic 0:c0ecb8bf28eb 18516 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18517 /*
Marko Mikulicic 0:c0ecb8bf28eb 18518 * We'll consult "set" property in case of the plain assignment only;
Marko Mikulicic 0:c0ecb8bf28eb 18519 * Object.defineProperty() has its own trap `defineProperty` which is not
Marko Mikulicic 0:c0ecb8bf28eb 18520 * yet implemented in v7
Marko Mikulicic 0:c0ecb8bf28eb 18521 */
Marko Mikulicic 0:c0ecb8bf28eb 18522 if (as_assign) {
Marko Mikulicic 0:c0ecb8bf28eb 18523 V7_TRY2(v7_get_throwing(v7, handler_v, "set", ~0, &set_v), clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18524 }
Marko Mikulicic 0:c0ecb8bf28eb 18525
Marko Mikulicic 0:c0ecb8bf28eb 18526 if (v7_is_callable(v7, set_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18527 /* The `set` callback is actually callable, so, use it */
Marko Mikulicic 0:c0ecb8bf28eb 18528
Marko Mikulicic 0:c0ecb8bf28eb 18529 /* prepare arguments for the callback */
Marko Mikulicic 0:c0ecb8bf28eb 18530 set_args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18531 /*
Marko Mikulicic 0:c0ecb8bf28eb 18532 * TODO(dfrank): don't copy string in case we already have val_t
Marko Mikulicic 0:c0ecb8bf28eb 18533 * (we need some generic function which will take both const char * and
Marko Mikulicic 0:c0ecb8bf28eb 18534 * val_t for that)
Marko Mikulicic 0:c0ecb8bf28eb 18535 */
Marko Mikulicic 0:c0ecb8bf28eb 18536 v7_array_set(v7, set_args_v, 0, target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18537 v7_array_set(v7, set_args_v, 1, name);
Marko Mikulicic 0:c0ecb8bf28eb 18538 v7_array_set(v7, set_args_v, 2, val);
Marko Mikulicic 0:c0ecb8bf28eb 18539
Marko Mikulicic 0:c0ecb8bf28eb 18540 /* call `set` callback */
Marko Mikulicic 0:c0ecb8bf28eb 18541 V7_TRY2(b_apply(v7, set_v, V7_UNDEFINED, set_args_v, 0, &val),
Marko Mikulicic 0:c0ecb8bf28eb 18542 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18543
Marko Mikulicic 0:c0ecb8bf28eb 18544 /* in strict mode, we should throw if trap returned falsy value */
Marko Mikulicic 0:c0ecb8bf28eb 18545 if (is_strict_mode(v7) && !v7_is_truthy(v7, val)) {
Marko Mikulicic 0:c0ecb8bf28eb 18546 V7_THROW2(
Marko Mikulicic 0:c0ecb8bf28eb 18547 v7_throwf(v7, TYPE_ERROR, "Trap returned falsy for property '%s'",
Marko Mikulicic 0:c0ecb8bf28eb 18548 v7_get_string(v7, &name, NULL)),
Marko Mikulicic 0:c0ecb8bf28eb 18549 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18550 }
Marko Mikulicic 0:c0ecb8bf28eb 18551
Marko Mikulicic 0:c0ecb8bf28eb 18552 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18553 /*
Marko Mikulicic 0:c0ecb8bf28eb 18554 * there's no `set` callback: then, set property on the target object
Marko Mikulicic 0:c0ecb8bf28eb 18555 * (not on the proxy object)
Marko Mikulicic 0:c0ecb8bf28eb 18556 */
Marko Mikulicic 0:c0ecb8bf28eb 18557 V7_TRY2(
Marko Mikulicic 0:c0ecb8bf28eb 18558 def_property_v(v7, target_v, name, attrs_desc, val, as_assign, res),
Marko Mikulicic 0:c0ecb8bf28eb 18559 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18560 }
Marko Mikulicic 0:c0ecb8bf28eb 18561
Marko Mikulicic 0:c0ecb8bf28eb 18562 clean_proxy:
Marko Mikulicic 0:c0ecb8bf28eb 18563 v7_disown(v7, &set_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18564 v7_disown(v7, &set_v);
Marko Mikulicic 0:c0ecb8bf28eb 18565 v7_disown(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18566 v7_disown(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18567 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18568 }
Marko Mikulicic 0:c0ecb8bf28eb 18569 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18570
Marko Mikulicic 0:c0ecb8bf28eb 18571 /* regular (non-proxy) property access */
Marko Mikulicic 0:c0ecb8bf28eb 18572 prop = v7_get_own_property(v7, obj, n, len);
Marko Mikulicic 0:c0ecb8bf28eb 18573 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18574 /*
Marko Mikulicic 0:c0ecb8bf28eb 18575 * The own property with given `name` doesn't exist yet: try to create it,
Marko Mikulicic 0:c0ecb8bf28eb 18576 * set requested `name` and `attributes`, and append to the object's
Marko Mikulicic 0:c0ecb8bf28eb 18577 * properties
Marko Mikulicic 0:c0ecb8bf28eb 18578 */
Marko Mikulicic 0:c0ecb8bf28eb 18579
Marko Mikulicic 0:c0ecb8bf28eb 18580 /* make sure the object is extensible */
Marko Mikulicic 0:c0ecb8bf28eb 18581 if (get_object_struct(obj)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18582 /*
Marko Mikulicic 0:c0ecb8bf28eb 18583 * We should throw if we use `Object.defineProperty`, or if we're in
Marko Mikulicic 0:c0ecb8bf28eb 18584 * strict mode.
Marko Mikulicic 0:c0ecb8bf28eb 18585 */
Marko Mikulicic 0:c0ecb8bf28eb 18586 if (is_strict_mode(v7) || !as_assign) {
Marko Mikulicic 0:c0ecb8bf28eb 18587 V7_THROW(v7_throwf(v7, TYPE_ERROR, "Object is not extensible"));
Marko Mikulicic 0:c0ecb8bf28eb 18588 }
Marko Mikulicic 0:c0ecb8bf28eb 18589 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18590 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18591 }
Marko Mikulicic 0:c0ecb8bf28eb 18592
Marko Mikulicic 0:c0ecb8bf28eb 18593 if ((prop = v7_mk_property(v7)) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18594 prop = NULL; /* LCOV_EXCL_LINE */
Marko Mikulicic 0:c0ecb8bf28eb 18595 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18596 }
Marko Mikulicic 0:c0ecb8bf28eb 18597 prop->name = name;
Marko Mikulicic 0:c0ecb8bf28eb 18598 prop->value = val;
Marko Mikulicic 0:c0ecb8bf28eb 18599 prop->attributes = apply_attrs_desc(attrs_desc, V7_DEFAULT_PROPERTY_ATTRS);
Marko Mikulicic 0:c0ecb8bf28eb 18600
Marko Mikulicic 0:c0ecb8bf28eb 18601 prop->next = get_object_struct(obj)->properties;
Marko Mikulicic 0:c0ecb8bf28eb 18602 get_object_struct(obj)->properties = prop;
Marko Mikulicic 0:c0ecb8bf28eb 18603 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18604 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18605 /* Property already exists */
Marko Mikulicic 0:c0ecb8bf28eb 18606
Marko Mikulicic 0:c0ecb8bf28eb 18607 if (prop->attributes & V7_PROPERTY_NON_WRITABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18608 /* The property is read-only */
Marko Mikulicic 0:c0ecb8bf28eb 18609
Marko Mikulicic 0:c0ecb8bf28eb 18610 if (as_assign) {
Marko Mikulicic 0:c0ecb8bf28eb 18611 /* Plain assignment: in strict mode throw, otherwise ignore */
Marko Mikulicic 0:c0ecb8bf28eb 18612 if (is_strict_mode(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 18613 V7_THROW(
Marko Mikulicic 0:c0ecb8bf28eb 18614 v7_throwf(v7, TYPE_ERROR, "Cannot assign to read-only property"));
Marko Mikulicic 0:c0ecb8bf28eb 18615 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18616 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18617 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18618 }
Marko Mikulicic 0:c0ecb8bf28eb 18619 } else if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18620 /*
Marko Mikulicic 0:c0ecb8bf28eb 18621 * Use `Object.defineProperty` semantic, and the property is
Marko Mikulicic 0:c0ecb8bf28eb 18622 * non-configurable: if no value is provided, or if new value is equal
Marko Mikulicic 0:c0ecb8bf28eb 18623 * to the existing one, then just fall through to change attributes;
Marko Mikulicic 0:c0ecb8bf28eb 18624 * otherwise, throw.
Marko Mikulicic 0:c0ecb8bf28eb 18625 */
Marko Mikulicic 0:c0ecb8bf28eb 18626
Marko Mikulicic 0:c0ecb8bf28eb 18627 if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) {
Marko Mikulicic 0:c0ecb8bf28eb 18628 uint8_t equal = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18629 if (v7_is_string(val) && v7_is_string(prop->value)) {
Marko Mikulicic 0:c0ecb8bf28eb 18630 equal = (s_cmp(v7, val, prop->value) == 0);
Marko Mikulicic 0:c0ecb8bf28eb 18631 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18632 equal = (val == prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 18633 }
Marko Mikulicic 0:c0ecb8bf28eb 18634
Marko Mikulicic 0:c0ecb8bf28eb 18635 if (!equal) {
Marko Mikulicic 0:c0ecb8bf28eb 18636 /* Values are not equal: should throw */
Marko Mikulicic 0:c0ecb8bf28eb 18637 V7_THROW(v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 18638 "Cannot redefine read-only property"));
Marko Mikulicic 0:c0ecb8bf28eb 18639 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18640 /*
Marko Mikulicic 0:c0ecb8bf28eb 18641 * Values are equal. Will fall through so that attributes might
Marko Mikulicic 0:c0ecb8bf28eb 18642 * change.
Marko Mikulicic 0:c0ecb8bf28eb 18643 */
Marko Mikulicic 0:c0ecb8bf28eb 18644 }
Marko Mikulicic 0:c0ecb8bf28eb 18645 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18646 /*
Marko Mikulicic 0:c0ecb8bf28eb 18647 * No value is provided. Will fall through so that attributes might
Marko Mikulicic 0:c0ecb8bf28eb 18648 * change.
Marko Mikulicic 0:c0ecb8bf28eb 18649 */
Marko Mikulicic 0:c0ecb8bf28eb 18650 }
Marko Mikulicic 0:c0ecb8bf28eb 18651 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18652 /*
Marko Mikulicic 0:c0ecb8bf28eb 18653 * Use `Object.defineProperty` semantic, and the property is
Marko Mikulicic 0:c0ecb8bf28eb 18654 * configurable: will fall through and assign new value, effectively
Marko Mikulicic 0:c0ecb8bf28eb 18655 * ignoring non-writable flag. This is the same as making a property
Marko Mikulicic 0:c0ecb8bf28eb 18656 * writable, then assigning a new value, and making a property
Marko Mikulicic 0:c0ecb8bf28eb 18657 * non-writable again.
Marko Mikulicic 0:c0ecb8bf28eb 18658 */
Marko Mikulicic 0:c0ecb8bf28eb 18659 }
Marko Mikulicic 0:c0ecb8bf28eb 18660 } else if (prop->attributes & V7_PROPERTY_SETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18661 /* Invoke setter */
Marko Mikulicic 0:c0ecb8bf28eb 18662 V7_TRY(v7_invoke_setter(v7, prop, obj, val));
Marko Mikulicic 0:c0ecb8bf28eb 18663 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18664 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18665 }
Marko Mikulicic 0:c0ecb8bf28eb 18666
Marko Mikulicic 0:c0ecb8bf28eb 18667 /* Set value and apply attrs delta */
Marko Mikulicic 0:c0ecb8bf28eb 18668 if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) {
Marko Mikulicic 0:c0ecb8bf28eb 18669 prop->value = val;
Marko Mikulicic 0:c0ecb8bf28eb 18670 }
Marko Mikulicic 0:c0ecb8bf28eb 18671 prop->attributes = apply_attrs_desc(attrs_desc, prop->attributes);
Marko Mikulicic 0:c0ecb8bf28eb 18672 }
Marko Mikulicic 0:c0ecb8bf28eb 18673
Marko Mikulicic 0:c0ecb8bf28eb 18674 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18675
Marko Mikulicic 0:c0ecb8bf28eb 18676 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18677 *res = prop;
Marko Mikulicic 0:c0ecb8bf28eb 18678 }
Marko Mikulicic 0:c0ecb8bf28eb 18679
Marko Mikulicic 0:c0ecb8bf28eb 18680 v7_disown(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18681 v7_disown(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 18682
Marko Mikulicic 0:c0ecb8bf28eb 18683 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18684 }
Marko Mikulicic 0:c0ecb8bf28eb 18685
Marko Mikulicic 0:c0ecb8bf28eb 18686 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18687 V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18688 size_t len, v7_prop_attr_desc_t attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 18689 v7_val_t val, uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 18690 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18691 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18692 val_t name_val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18693
Marko Mikulicic 0:c0ecb8bf28eb 18694 v7_own(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18695 v7_own(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18696 v7_own(v7, &name_val);
Marko Mikulicic 0:c0ecb8bf28eb 18697
Marko Mikulicic 0:c0ecb8bf28eb 18698 if (len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18699 len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18700 }
Marko Mikulicic 0:c0ecb8bf28eb 18701
Marko Mikulicic 0:c0ecb8bf28eb 18702 name_val = v7_mk_string(v7, name, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18703 V7_TRY(def_property_v(v7, obj, name_val, attrs_desc, val, as_assign, res));
Marko Mikulicic 0:c0ecb8bf28eb 18704
Marko Mikulicic 0:c0ecb8bf28eb 18705 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18706 v7_disown(v7, &name_val);
Marko Mikulicic 0:c0ecb8bf28eb 18707 v7_disown(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18708 v7_disown(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18709
Marko Mikulicic 0:c0ecb8bf28eb 18710 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18711 }
Marko Mikulicic 0:c0ecb8bf28eb 18712
Marko Mikulicic 0:c0ecb8bf28eb 18713 V7_PRIVATE int set_method(struct v7 *v7, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18714 v7_cfunction_t *func, int num_args) {
Marko Mikulicic 0:c0ecb8bf28eb 18715 return v7_def(v7, obj, name, strlen(name), V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 18716 mk_cfunction_obj(v7, func, num_args));
Marko Mikulicic 0:c0ecb8bf28eb 18717 }
Marko Mikulicic 0:c0ecb8bf28eb 18718
Marko Mikulicic 0:c0ecb8bf28eb 18719 int v7_set_method(struct v7 *v7, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18720 v7_cfunction_t *func) {
Marko Mikulicic 0:c0ecb8bf28eb 18721 return set_method(v7, obj, name, func, ~0);
Marko Mikulicic 0:c0ecb8bf28eb 18722 }
Marko Mikulicic 0:c0ecb8bf28eb 18723
Marko Mikulicic 0:c0ecb8bf28eb 18724 V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18725 v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 18726 return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 18727 v7_mk_cfunction(f));
Marko Mikulicic 0:c0ecb8bf28eb 18728 }
Marko Mikulicic 0:c0ecb8bf28eb 18729
Marko Mikulicic 0:c0ecb8bf28eb 18730 /*
Marko Mikulicic 0:c0ecb8bf28eb 18731 * See comments in `object_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 18732 */
Marko Mikulicic 0:c0ecb8bf28eb 18733 int v7_del(struct v7 *v7, val_t obj, const char *name, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 18734 struct v7_property *prop, *prev;
Marko Mikulicic 0:c0ecb8bf28eb 18735
Marko Mikulicic 0:c0ecb8bf28eb 18736 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18737 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 18738 }
Marko Mikulicic 0:c0ecb8bf28eb 18739 if (len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18740 len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18741 }
Marko Mikulicic 0:c0ecb8bf28eb 18742 for (prev = NULL, prop = get_object_struct(obj)->properties; prop != NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18743 prev = prop, prop = prop->next) {
Marko Mikulicic 0:c0ecb8bf28eb 18744 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 18745 const char *s = v7_get_string(v7, &prop->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 18746 if (n == len && strncmp(s, name, len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 18747 if (prev) {
Marko Mikulicic 0:c0ecb8bf28eb 18748 prev->next = prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 18749 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18750 get_object_struct(obj)->properties = prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 18751 }
Marko Mikulicic 0:c0ecb8bf28eb 18752 v7_destroy_property(&prop);
Marko Mikulicic 0:c0ecb8bf28eb 18753 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 18754 }
Marko Mikulicic 0:c0ecb8bf28eb 18755 }
Marko Mikulicic 0:c0ecb8bf28eb 18756 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 18757 }
Marko Mikulicic 0:c0ecb8bf28eb 18758
Marko Mikulicic 0:c0ecb8bf28eb 18759 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18760 V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18761 struct v7_property *p, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 18762 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18763 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18764 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18765 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18766 }
Marko Mikulicic 0:c0ecb8bf28eb 18767 if (p->attributes & V7_PROPERTY_GETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18768 val_t getter = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 18769 if (p->attributes & V7_PROPERTY_SETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18770 getter = v7_array_get(v7, p->value, 0);
Marko Mikulicic 0:c0ecb8bf28eb 18771 }
Marko Mikulicic 0:c0ecb8bf28eb 18772 {
Marko Mikulicic 0:c0ecb8bf28eb 18773 V7_TRY(b_apply(v7, getter, obj, V7_UNDEFINED, 0, res));
Marko Mikulicic 0:c0ecb8bf28eb 18774 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18775 }
Marko Mikulicic 0:c0ecb8bf28eb 18776 }
Marko Mikulicic 0:c0ecb8bf28eb 18777
Marko Mikulicic 0:c0ecb8bf28eb 18778 *res = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 18779 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18780
Marko Mikulicic 0:c0ecb8bf28eb 18781 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18782 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18783 }
Marko Mikulicic 0:c0ecb8bf28eb 18784
Marko Mikulicic 0:c0ecb8bf28eb 18785 enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18786 struct prop_iter_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 18787 return init_prop_iter_ctx(v7, obj, 1 /*proxy-transparent*/, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 18788 }
Marko Mikulicic 0:c0ecb8bf28eb 18789
Marko Mikulicic 0:c0ecb8bf28eb 18790 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18791 V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18792 int proxy_transp,
Marko Mikulicic 0:c0ecb8bf28eb 18793 struct prop_iter_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 18794 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18795
Marko Mikulicic 0:c0ecb8bf28eb 18796 v7_own(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18797
Marko Mikulicic 0:c0ecb8bf28eb 18798 memset(ctx, 0x00, sizeof(*ctx));
Marko Mikulicic 0:c0ecb8bf28eb 18799
Marko Mikulicic 0:c0ecb8bf28eb 18800 if (v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18801 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18802 if (proxy_transp && get_object_struct(obj)->attributes & V7_OBJ_PROXY) {
Marko Mikulicic 0:c0ecb8bf28eb 18803 v7_val_t ownKeys_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18804 v7_val_t args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18805
Marko Mikulicic 0:c0ecb8bf28eb 18806 v7_own(v7, &ownKeys_v);
Marko Mikulicic 0:c0ecb8bf28eb 18807 v7_own(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18808
Marko Mikulicic 0:c0ecb8bf28eb 18809 ctx->proxy_ctx =
Marko Mikulicic 0:c0ecb8bf28eb 18810 (struct prop_iter_proxy_ctx *) calloc(1, sizeof(*ctx->proxy_ctx));
Marko Mikulicic 0:c0ecb8bf28eb 18811
Marko Mikulicic 0:c0ecb8bf28eb 18812 ctx->proxy_ctx->target_obj = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18813 ctx->proxy_ctx->handler_obj = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18814 ctx->proxy_ctx->own_keys = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18815 ctx->proxy_ctx->get_own_prop_desc = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18816
Marko Mikulicic 0:c0ecb8bf28eb 18817 v7_own(v7, &ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18818 v7_own(v7, &ctx->proxy_ctx->handler_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18819 v7_own(v7, &ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 18820 v7_own(v7, &ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18821
Marko Mikulicic 0:c0ecb8bf28eb 18822 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18823 &ctx->proxy_ctx->target_obj),
Marko Mikulicic 0:c0ecb8bf28eb 18824 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18825 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18826 &ctx->proxy_ctx->handler_obj),
Marko Mikulicic 0:c0ecb8bf28eb 18827 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18828
Marko Mikulicic 0:c0ecb8bf28eb 18829 V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "ownKeys", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18830 &ownKeys_v),
Marko Mikulicic 0:c0ecb8bf28eb 18831 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18832
Marko Mikulicic 0:c0ecb8bf28eb 18833 if (v7_is_callable(v7, ownKeys_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18834 /* prepare arguments for the ownKeys callback */
Marko Mikulicic 0:c0ecb8bf28eb 18835 args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18836 v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18837
Marko Mikulicic 0:c0ecb8bf28eb 18838 /* call `ownKeys` callback, and save the result in context */
Marko Mikulicic 0:c0ecb8bf28eb 18839 V7_TRY2(b_apply(v7, ownKeys_v, V7_UNDEFINED, args_v, 0,
Marko Mikulicic 0:c0ecb8bf28eb 18840 &ctx->proxy_ctx->own_keys),
Marko Mikulicic 0:c0ecb8bf28eb 18841 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18842
Marko Mikulicic 0:c0ecb8bf28eb 18843 ctx->proxy_ctx->has_own_keys = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18844 ctx->proxy_ctx->own_key_idx = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18845
Marko Mikulicic 0:c0ecb8bf28eb 18846 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18847 /*
Marko Mikulicic 0:c0ecb8bf28eb 18848 * No ownKeys callback, so we'll iterate real properties of the target
Marko Mikulicic 0:c0ecb8bf28eb 18849 * object
Marko Mikulicic 0:c0ecb8bf28eb 18850 */
Marko Mikulicic 0:c0ecb8bf28eb 18851
Marko Mikulicic 0:c0ecb8bf28eb 18852 /*
Marko Mikulicic 0:c0ecb8bf28eb 18853 * TODO(dfrank): add support for the target object which is a proxy as
Marko Mikulicic 0:c0ecb8bf28eb 18854 * well
Marko Mikulicic 0:c0ecb8bf28eb 18855 */
Marko Mikulicic 0:c0ecb8bf28eb 18856 ctx->cur_prop =
Marko Mikulicic 0:c0ecb8bf28eb 18857 get_object_struct(ctx->proxy_ctx->target_obj)->properties;
Marko Mikulicic 0:c0ecb8bf28eb 18858 }
Marko Mikulicic 0:c0ecb8bf28eb 18859
Marko Mikulicic 0:c0ecb8bf28eb 18860 V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "_gpdc", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18861 &ctx->proxy_ctx->get_own_prop_desc),
Marko Mikulicic 0:c0ecb8bf28eb 18862 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18863 if (v7_is_foreign(ctx->proxy_ctx->get_own_prop_desc)) {
Marko Mikulicic 0:c0ecb8bf28eb 18864 /*
Marko Mikulicic 0:c0ecb8bf28eb 18865 * C callback for getting property descriptor is provided: will use it
Marko Mikulicic 0:c0ecb8bf28eb 18866 */
Marko Mikulicic 0:c0ecb8bf28eb 18867 ctx->proxy_ctx->has_get_own_prop_desc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18868 ctx->proxy_ctx->has_get_own_prop_desc_C = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18869 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18870 /*
Marko Mikulicic 0:c0ecb8bf28eb 18871 * No C callback for getting property descriptor is provided, let's
Marko Mikulicic 0:c0ecb8bf28eb 18872 * check if there is a JS one..
Marko Mikulicic 0:c0ecb8bf28eb 18873 */
Marko Mikulicic 0:c0ecb8bf28eb 18874 V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj,
Marko Mikulicic 0:c0ecb8bf28eb 18875 "getOwnPropertyDescriptor", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18876 &ctx->proxy_ctx->get_own_prop_desc),
Marko Mikulicic 0:c0ecb8bf28eb 18877 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18878
Marko Mikulicic 0:c0ecb8bf28eb 18879 if (v7_is_callable(v7, ctx->proxy_ctx->get_own_prop_desc)) {
Marko Mikulicic 0:c0ecb8bf28eb 18880 /* Yes there is, we'll use it */
Marko Mikulicic 0:c0ecb8bf28eb 18881 ctx->proxy_ctx->has_get_own_prop_desc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18882 }
Marko Mikulicic 0:c0ecb8bf28eb 18883 }
Marko Mikulicic 0:c0ecb8bf28eb 18884
Marko Mikulicic 0:c0ecb8bf28eb 18885 clean_proxy:
Marko Mikulicic 0:c0ecb8bf28eb 18886 v7_disown(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18887 v7_disown(v7, &ownKeys_v);
Marko Mikulicic 0:c0ecb8bf28eb 18888
Marko Mikulicic 0:c0ecb8bf28eb 18889 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18890 /* something went wrong, so, disown values in the context and free it */
Marko Mikulicic 0:c0ecb8bf28eb 18891 v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18892 v7_disown(v7, &ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 18893 v7_disown(v7, &ctx->proxy_ctx->handler_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18894 v7_disown(v7, &ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18895
Marko Mikulicic 0:c0ecb8bf28eb 18896 free(ctx->proxy_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 18897 ctx->proxy_ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18898
Marko Mikulicic 0:c0ecb8bf28eb 18899 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18900 }
Marko Mikulicic 0:c0ecb8bf28eb 18901 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18902 #else
Marko Mikulicic 0:c0ecb8bf28eb 18903 (void) proxy_transp;
Marko Mikulicic 0:c0ecb8bf28eb 18904 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18905
Marko Mikulicic 0:c0ecb8bf28eb 18906 /* Object is not a proxy: we'll iterate real properties */
Marko Mikulicic 0:c0ecb8bf28eb 18907 ctx->cur_prop = get_object_struct(obj)->properties;
Marko Mikulicic 0:c0ecb8bf28eb 18908
Marko Mikulicic 0:c0ecb8bf28eb 18909 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18910 }
Marko Mikulicic 0:c0ecb8bf28eb 18911 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18912 }
Marko Mikulicic 0:c0ecb8bf28eb 18913
Marko Mikulicic 0:c0ecb8bf28eb 18914 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18915 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18916 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18917 v7_disown(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18918 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18919 ctx->init = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18920 }
Marko Mikulicic 0:c0ecb8bf28eb 18921 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18922 }
Marko Mikulicic 0:c0ecb8bf28eb 18923
Marko Mikulicic 0:c0ecb8bf28eb 18924 void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 18925 if (ctx->init) {
Marko Mikulicic 0:c0ecb8bf28eb 18926 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18927 if (ctx->proxy_ctx != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18928 v7_disown(v7, &ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18929 v7_disown(v7, &ctx->proxy_ctx->handler_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18930 v7_disown(v7, &ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 18931 v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18932 }
Marko Mikulicic 0:c0ecb8bf28eb 18933 free(ctx->proxy_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 18934 ctx->proxy_ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18935 #else
Marko Mikulicic 0:c0ecb8bf28eb 18936 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 18937 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18938 ctx->init = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18939 }
Marko Mikulicic 0:c0ecb8bf28eb 18940 }
Marko Mikulicic 0:c0ecb8bf28eb 18941
Marko Mikulicic 0:c0ecb8bf28eb 18942 int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name,
Marko Mikulicic 0:c0ecb8bf28eb 18943 v7_val_t *value, v7_prop_attr_t *attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 18944 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18945 if (next_prop(v7, ctx, name, value, attrs, &ok) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18946 fprintf(stderr, "next_prop failed\n");
Marko Mikulicic 0:c0ecb8bf28eb 18947 ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18948 }
Marko Mikulicic 0:c0ecb8bf28eb 18949 return ok;
Marko Mikulicic 0:c0ecb8bf28eb 18950 }
Marko Mikulicic 0:c0ecb8bf28eb 18951
Marko Mikulicic 0:c0ecb8bf28eb 18952 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18953 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18954 static enum v7_err get_custom_prop_desc(struct v7 *v7, v7_val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18955 struct prop_iter_ctx *ctx,
Marko Mikulicic 0:c0ecb8bf28eb 18956 struct v7_property *res_prop, int *ok) {
Marko Mikulicic 0:c0ecb8bf28eb 18957 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18958
Marko Mikulicic 0:c0ecb8bf28eb 18959 v7_val_t args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18960 v7_val_t desc_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18961 v7_val_t tmpflag_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18962
Marko Mikulicic 0:c0ecb8bf28eb 18963 v7_own(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 18964 v7_own(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18965 v7_own(v7, &desc_v);
Marko Mikulicic 0:c0ecb8bf28eb 18966 v7_own(v7, &tmpflag_v);
Marko Mikulicic 0:c0ecb8bf28eb 18967
Marko Mikulicic 0:c0ecb8bf28eb 18968 *ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18969
Marko Mikulicic 0:c0ecb8bf28eb 18970 if (ctx->proxy_ctx->has_get_own_prop_desc_C) {
Marko Mikulicic 0:c0ecb8bf28eb 18971 /*
Marko Mikulicic 0:c0ecb8bf28eb 18972 * There is a C callback which should fill the property descriptor
Marko Mikulicic 0:c0ecb8bf28eb 18973 * structure, see `v7_get_own_prop_desc_cb_t`
Marko Mikulicic 0:c0ecb8bf28eb 18974 */
Marko Mikulicic 0:c0ecb8bf28eb 18975 v7_get_own_prop_desc_cb_t *cb = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18976 memset(res_prop, 0, sizeof(*res_prop));
Marko Mikulicic 0:c0ecb8bf28eb 18977 cb = (v7_get_own_prop_desc_cb_t *) v7_get_ptr(
Marko Mikulicic 0:c0ecb8bf28eb 18978 v7, ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18979
Marko Mikulicic 0:c0ecb8bf28eb 18980 res_prop->attributes = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18981 res_prop->value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18982
Marko Mikulicic 0:c0ecb8bf28eb 18983 *ok = !!cb(v7, ctx->proxy_ctx->target_obj, name, &res_prop->attributes,
Marko Mikulicic 0:c0ecb8bf28eb 18984 &res_prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 18985 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18986 /* prepare arguments for the getOwnPropertyDescriptor callback */
Marko Mikulicic 0:c0ecb8bf28eb 18987 args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18988 v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18989 v7_array_set(v7, args_v, 1, name);
Marko Mikulicic 0:c0ecb8bf28eb 18990
Marko Mikulicic 0:c0ecb8bf28eb 18991 /* call getOwnPropertyDescriptor callback */
Marko Mikulicic 0:c0ecb8bf28eb 18992 V7_TRY(b_apply(v7, ctx->proxy_ctx->get_own_prop_desc, V7_UNDEFINED, args_v,
Marko Mikulicic 0:c0ecb8bf28eb 18993 0, &desc_v));
Marko Mikulicic 0:c0ecb8bf28eb 18994
Marko Mikulicic 0:c0ecb8bf28eb 18995 if (v7_is_object(desc_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18996 res_prop->attributes = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18997
Marko Mikulicic 0:c0ecb8bf28eb 18998 V7_TRY(v7_get_throwing(v7, desc_v, "writable", ~0, &tmpflag_v));
Marko Mikulicic 0:c0ecb8bf28eb 18999 if (!v7_is_truthy(v7, tmpflag_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19000 res_prop->attributes |= V7_PROPERTY_NON_WRITABLE;
Marko Mikulicic 0:c0ecb8bf28eb 19001 }
Marko Mikulicic 0:c0ecb8bf28eb 19002
Marko Mikulicic 0:c0ecb8bf28eb 19003 V7_TRY(v7_get_throwing(v7, desc_v, "configurable", ~0, &tmpflag_v));
Marko Mikulicic 0:c0ecb8bf28eb 19004 if (!v7_is_truthy(v7, tmpflag_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19005 res_prop->attributes |= V7_PROPERTY_NON_CONFIGURABLE;
Marko Mikulicic 0:c0ecb8bf28eb 19006 }
Marko Mikulicic 0:c0ecb8bf28eb 19007
Marko Mikulicic 0:c0ecb8bf28eb 19008 V7_TRY(v7_get_throwing(v7, desc_v, "enumerable", ~0, &tmpflag_v));
Marko Mikulicic 0:c0ecb8bf28eb 19009 if (!v7_is_truthy(v7, tmpflag_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19010 res_prop->attributes |= V7_PROPERTY_NON_ENUMERABLE;
Marko Mikulicic 0:c0ecb8bf28eb 19011 }
Marko Mikulicic 0:c0ecb8bf28eb 19012
Marko Mikulicic 0:c0ecb8bf28eb 19013 V7_TRY(v7_get_throwing(v7, desc_v, "value", ~0, &res_prop->value));
Marko Mikulicic 0:c0ecb8bf28eb 19014
Marko Mikulicic 0:c0ecb8bf28eb 19015 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19016 }
Marko Mikulicic 0:c0ecb8bf28eb 19017 }
Marko Mikulicic 0:c0ecb8bf28eb 19018
Marko Mikulicic 0:c0ecb8bf28eb 19019 /* We always set the name in the property descriptor to the actual name */
Marko Mikulicic 0:c0ecb8bf28eb 19020 res_prop->name = name;
Marko Mikulicic 0:c0ecb8bf28eb 19021
Marko Mikulicic 0:c0ecb8bf28eb 19022 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19023 v7_disown(v7, &tmpflag_v);
Marko Mikulicic 0:c0ecb8bf28eb 19024 v7_disown(v7, &desc_v);
Marko Mikulicic 0:c0ecb8bf28eb 19025 v7_disown(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 19026 v7_disown(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 19027
Marko Mikulicic 0:c0ecb8bf28eb 19028 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19029 }
Marko Mikulicic 0:c0ecb8bf28eb 19030 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19031
Marko Mikulicic 0:c0ecb8bf28eb 19032 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19033 V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx,
Marko Mikulicic 0:c0ecb8bf28eb 19034 v7_val_t *name, v7_val_t *value,
Marko Mikulicic 0:c0ecb8bf28eb 19035 v7_prop_attr_t *attrs, int *ok) {
Marko Mikulicic 0:c0ecb8bf28eb 19036 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19037 struct v7_property p;
Marko Mikulicic 0:c0ecb8bf28eb 19038
Marko Mikulicic 0:c0ecb8bf28eb 19039 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19040
Marko Mikulicic 0:c0ecb8bf28eb 19041 memset(&p, 0, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 19042 p.name = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19043 p.value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19044
Marko Mikulicic 0:c0ecb8bf28eb 19045 v7_own(v7, &p.name);
Marko Mikulicic 0:c0ecb8bf28eb 19046 v7_own(v7, &p.value);
Marko Mikulicic 0:c0ecb8bf28eb 19047
Marko Mikulicic 0:c0ecb8bf28eb 19048 assert(ctx->init);
Marko Mikulicic 0:c0ecb8bf28eb 19049
Marko Mikulicic 0:c0ecb8bf28eb 19050 *ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19051
Marko Mikulicic 0:c0ecb8bf28eb 19052 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 19053 if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_own_keys) {
Marko Mikulicic 0:c0ecb8bf28eb 19054 /*
Marko Mikulicic 0:c0ecb8bf28eb 19055 * No `ownKeys` callback, so we'll iterate real properties of the object
Marko Mikulicic 0:c0ecb8bf28eb 19056 * (either the given object or, if it's a proxy, the proxy's target object)
Marko Mikulicic 0:c0ecb8bf28eb 19057 */
Marko Mikulicic 0:c0ecb8bf28eb 19058
Marko Mikulicic 0:c0ecb8bf28eb 19059 if (ctx->cur_prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19060 if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_get_own_prop_desc) {
Marko Mikulicic 0:c0ecb8bf28eb 19061 /*
Marko Mikulicic 0:c0ecb8bf28eb 19062 * There is no `getOwnPropertyDescriptor` callback, so, use the current
Marko Mikulicic 0:c0ecb8bf28eb 19063 * real property
Marko Mikulicic 0:c0ecb8bf28eb 19064 */
Marko Mikulicic 0:c0ecb8bf28eb 19065 memcpy(&p, ctx->cur_prop, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 19066 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19067 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19068 /*
Marko Mikulicic 0:c0ecb8bf28eb 19069 * There is a `getOwnPropertyDescriptor` callback, so call it for the
Marko Mikulicic 0:c0ecb8bf28eb 19070 * name of the current real property
Marko Mikulicic 0:c0ecb8bf28eb 19071 */
Marko Mikulicic 0:c0ecb8bf28eb 19072 V7_TRY(get_custom_prop_desc(v7, ctx->cur_prop->name, ctx, &p, ok));
Marko Mikulicic 0:c0ecb8bf28eb 19073 }
Marko Mikulicic 0:c0ecb8bf28eb 19074
Marko Mikulicic 0:c0ecb8bf28eb 19075 ctx->cur_prop = ctx->cur_prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 19076 }
Marko Mikulicic 0:c0ecb8bf28eb 19077 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19078 /* We have custom own keys */
Marko Mikulicic 0:c0ecb8bf28eb 19079 v7_val_t cur_key = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19080 size_t len = v7_array_length(v7, ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 19081
Marko Mikulicic 0:c0ecb8bf28eb 19082 v7_own(v7, &cur_key);
Marko Mikulicic 0:c0ecb8bf28eb 19083
Marko Mikulicic 0:c0ecb8bf28eb 19084 /*
Marko Mikulicic 0:c0ecb8bf28eb 19085 * Iterate through the custom own keys until we can get the proper property
Marko Mikulicic 0:c0ecb8bf28eb 19086 * descriptor for the given key
Marko Mikulicic 0:c0ecb8bf28eb 19087 */
Marko Mikulicic 0:c0ecb8bf28eb 19088 while (!*ok && (size_t) ctx->proxy_ctx->own_key_idx < len) {
Marko Mikulicic 0:c0ecb8bf28eb 19089 cur_key = v7_array_get(v7, ctx->proxy_ctx->own_keys,
Marko Mikulicic 0:c0ecb8bf28eb 19090 ctx->proxy_ctx->own_key_idx);
Marko Mikulicic 0:c0ecb8bf28eb 19091 ctx->proxy_ctx->own_key_idx++;
Marko Mikulicic 0:c0ecb8bf28eb 19092
Marko Mikulicic 0:c0ecb8bf28eb 19093 if (ctx->proxy_ctx->has_get_own_prop_desc) {
Marko Mikulicic 0:c0ecb8bf28eb 19094 /*
Marko Mikulicic 0:c0ecb8bf28eb 19095 * There is a `getOwnPropertyDescriptor` callback, so, call it for the
Marko Mikulicic 0:c0ecb8bf28eb 19096 * current custom key and get all descriptor data from the object
Marko Mikulicic 0:c0ecb8bf28eb 19097 * returned. The `ok` variable will be updated appropriately (it will
Marko Mikulicic 0:c0ecb8bf28eb 19098 * be 0 if the callback did not return a proper descriptor)
Marko Mikulicic 0:c0ecb8bf28eb 19099 */
Marko Mikulicic 0:c0ecb8bf28eb 19100 V7_TRY2(get_custom_prop_desc(v7, cur_key, ctx, &p, ok), clean_custom);
Marko Mikulicic 0:c0ecb8bf28eb 19101 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19102 /*
Marko Mikulicic 0:c0ecb8bf28eb 19103 * There is no `getOwnPropertyDescriptor` callback, so, try to get
Marko Mikulicic 0:c0ecb8bf28eb 19104 * real property with the name equal to the current key
Marko Mikulicic 0:c0ecb8bf28eb 19105 */
Marko Mikulicic 0:c0ecb8bf28eb 19106 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19107 const char *name = v7_get_string(v7, &cur_key, &len);
Marko Mikulicic 0:c0ecb8bf28eb 19108
Marko Mikulicic 0:c0ecb8bf28eb 19109 struct v7_property *real_prop =
Marko Mikulicic 0:c0ecb8bf28eb 19110 v7_get_own_property(v7, ctx->proxy_ctx->target_obj, name, len);
Marko Mikulicic 0:c0ecb8bf28eb 19111 if (real_prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19112 /* Property exists, so use data from its descriptor */
Marko Mikulicic 0:c0ecb8bf28eb 19113 memcpy(&p, real_prop, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 19114 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19115 }
Marko Mikulicic 0:c0ecb8bf28eb 19116 }
Marko Mikulicic 0:c0ecb8bf28eb 19117 }
Marko Mikulicic 0:c0ecb8bf28eb 19118 clean_custom:
Marko Mikulicic 0:c0ecb8bf28eb 19119 v7_disown(v7, &cur_key);
Marko Mikulicic 0:c0ecb8bf28eb 19120 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19121 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19122 }
Marko Mikulicic 0:c0ecb8bf28eb 19123 }
Marko Mikulicic 0:c0ecb8bf28eb 19124
Marko Mikulicic 0:c0ecb8bf28eb 19125 #else
Marko Mikulicic 0:c0ecb8bf28eb 19126 /*
Marko Mikulicic 0:c0ecb8bf28eb 19127 * Proxy is disabled: just get the next property
Marko Mikulicic 0:c0ecb8bf28eb 19128 */
Marko Mikulicic 0:c0ecb8bf28eb 19129 if (ctx->cur_prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19130 memcpy(&p, ctx->cur_prop, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 19131 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19132 ctx->cur_prop = ctx->cur_prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 19133 }
Marko Mikulicic 0:c0ecb8bf28eb 19134 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19135
Marko Mikulicic 0:c0ecb8bf28eb 19136 /* If we have a valid property descriptor, use data from it */
Marko Mikulicic 0:c0ecb8bf28eb 19137 if (*ok) {
Marko Mikulicic 0:c0ecb8bf28eb 19138 if (name != NULL) *name = p.name;
Marko Mikulicic 0:c0ecb8bf28eb 19139 if (value != NULL) *value = p.value;
Marko Mikulicic 0:c0ecb8bf28eb 19140 if (attrs != NULL) *attrs = p.attributes;
Marko Mikulicic 0:c0ecb8bf28eb 19141 }
Marko Mikulicic 0:c0ecb8bf28eb 19142
Marko Mikulicic 0:c0ecb8bf28eb 19143 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 19144 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19145 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19146 v7_disown(v7, &p.value);
Marko Mikulicic 0:c0ecb8bf28eb 19147 v7_disown(v7, &p.name);
Marko Mikulicic 0:c0ecb8bf28eb 19148 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19149 }
Marko Mikulicic 0:c0ecb8bf28eb 19150
Marko Mikulicic 0:c0ecb8bf28eb 19151 /* }}} Object properties */
Marko Mikulicic 0:c0ecb8bf28eb 19152
Marko Mikulicic 0:c0ecb8bf28eb 19153 /* Object prototypes {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 19154
Marko Mikulicic 0:c0ecb8bf28eb 19155 V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj,
Marko Mikulicic 0:c0ecb8bf28eb 19156 struct v7_object *proto) {
Marko Mikulicic 0:c0ecb8bf28eb 19157 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 19158 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19159
Marko Mikulicic 0:c0ecb8bf28eb 19160 if (obj->attributes & V7_OBJ_FUNCTION) {
Marko Mikulicic 0:c0ecb8bf28eb 19161 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 19162 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19163 ((struct v7_generic_object *) obj)->prototype = proto;
Marko Mikulicic 0:c0ecb8bf28eb 19164 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19165 }
Marko Mikulicic 0:c0ecb8bf28eb 19166
Marko Mikulicic 0:c0ecb8bf28eb 19167 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 19168 }
Marko Mikulicic 0:c0ecb8bf28eb 19169
Marko Mikulicic 0:c0ecb8bf28eb 19170 V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 19171 struct v7_object *obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19172 if (obj->attributes & V7_OBJ_FUNCTION) {
Marko Mikulicic 0:c0ecb8bf28eb 19173 return get_object_struct(v7->vals.function_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 19174 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19175 return ((struct v7_generic_object *) obj)->prototype;
Marko Mikulicic 0:c0ecb8bf28eb 19176 }
Marko Mikulicic 0:c0ecb8bf28eb 19177 }
Marko Mikulicic 0:c0ecb8bf28eb 19178
Marko Mikulicic 0:c0ecb8bf28eb 19179 V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p) {
Marko Mikulicic 0:c0ecb8bf28eb 19180 if (!v7_is_object(o) || !v7_is_object(p)) {
Marko Mikulicic 0:c0ecb8bf28eb 19181 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19182 }
Marko Mikulicic 0:c0ecb8bf28eb 19183
Marko Mikulicic 0:c0ecb8bf28eb 19184 /* walk the prototype chain */
Marko Mikulicic 0:c0ecb8bf28eb 19185 for (; !v7_is_null(o); o = v7_get_proto(v7, o)) {
Marko Mikulicic 0:c0ecb8bf28eb 19186 if (v7_get_proto(v7, o) == p) {
Marko Mikulicic 0:c0ecb8bf28eb 19187 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 19188 }
Marko Mikulicic 0:c0ecb8bf28eb 19189 }
Marko Mikulicic 0:c0ecb8bf28eb 19190 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19191 }
Marko Mikulicic 0:c0ecb8bf28eb 19192
Marko Mikulicic 0:c0ecb8bf28eb 19193 int v7_is_instanceof(struct v7 *v7, val_t o, const char *c) {
Marko Mikulicic 0:c0ecb8bf28eb 19194 return v7_is_instanceof_v(v7, o, v7_get(v7, v7->vals.global_object, c, ~0));
Marko Mikulicic 0:c0ecb8bf28eb 19195 }
Marko Mikulicic 0:c0ecb8bf28eb 19196
Marko Mikulicic 0:c0ecb8bf28eb 19197 int v7_is_instanceof_v(struct v7 *v7, val_t o, val_t c) {
Marko Mikulicic 0:c0ecb8bf28eb 19198 return is_prototype_of(v7, o, v7_get(v7, c, "prototype", 9));
Marko Mikulicic 0:c0ecb8bf28eb 19199 }
Marko Mikulicic 0:c0ecb8bf28eb 19200
Marko Mikulicic 0:c0ecb8bf28eb 19201 v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 19202 if (v7_is_generic_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 19203 v7_val_t old_proto =
Marko Mikulicic 0:c0ecb8bf28eb 19204 v7_object_to_value(obj_prototype(v7, get_object_struct(obj)));
Marko Mikulicic 0:c0ecb8bf28eb 19205 obj_prototype_set(v7, get_object_struct(obj), get_object_struct(proto));
Marko Mikulicic 0:c0ecb8bf28eb 19206 return old_proto;
Marko Mikulicic 0:c0ecb8bf28eb 19207 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19208 return V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19209 }
Marko Mikulicic 0:c0ecb8bf28eb 19210 }
Marko Mikulicic 0:c0ecb8bf28eb 19211
Marko Mikulicic 0:c0ecb8bf28eb 19212 val_t v7_get_proto(struct v7 *v7, val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19213 /*
Marko Mikulicic 0:c0ecb8bf28eb 19214 * NOTE: we don't use v7_is_callable() here, because it involves walking
Marko Mikulicic 0:c0ecb8bf28eb 19215 * through the object's properties, which may be expensive. And it's done
Marko Mikulicic 0:c0ecb8bf28eb 19216 * anyway for cfunction objects as it would for any other generic objects by
Marko Mikulicic 0:c0ecb8bf28eb 19217 * the call to `obj_prototype()`.
Marko Mikulicic 0:c0ecb8bf28eb 19218 *
Marko Mikulicic 0:c0ecb8bf28eb 19219 * Since this function is called quite often (at least, GC walks the
Marko Mikulicic 0:c0ecb8bf28eb 19220 * prototype chain), it's better to just handle cfunction objects as generic
Marko Mikulicic 0:c0ecb8bf28eb 19221 * objects.
Marko Mikulicic 0:c0ecb8bf28eb 19222 */
Marko Mikulicic 0:c0ecb8bf28eb 19223 if (is_js_function(obj) || is_cfunction_lite(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 19224 return v7->vals.function_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 19225 }
Marko Mikulicic 0:c0ecb8bf28eb 19226 return v7_object_to_value(obj_prototype(v7, get_object_struct(obj)));
Marko Mikulicic 0:c0ecb8bf28eb 19227 }
Marko Mikulicic 0:c0ecb8bf28eb 19228
Marko Mikulicic 0:c0ecb8bf28eb 19229 V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19230 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 19231 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 19232 if (!v7_is_object(obj)) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19233 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19234
Marko Mikulicic 0:c0ecb8bf28eb 19235 for (p = o->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 19236 if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) {
Marko Mikulicic 0:c0ecb8bf28eb 19237 return p;
Marko Mikulicic 0:c0ecb8bf28eb 19238 }
Marko Mikulicic 0:c0ecb8bf28eb 19239 }
Marko Mikulicic 0:c0ecb8bf28eb 19240
Marko Mikulicic 0:c0ecb8bf28eb 19241 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19242 }
Marko Mikulicic 0:c0ecb8bf28eb 19243
Marko Mikulicic 0:c0ecb8bf28eb 19244 /*
Marko Mikulicic 0:c0ecb8bf28eb 19245 * Returns the user data property structure associated with obj, or NULL if
Marko Mikulicic 0:c0ecb8bf28eb 19246 * `obj` is not an object.
Marko Mikulicic 0:c0ecb8bf28eb 19247 */
Marko Mikulicic 0:c0ecb8bf28eb 19248 static struct v7_property *get_or_create_user_data_property(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 19249 v7_val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19250 struct v7_property *p = get_user_data_property(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19251 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 19252
Marko Mikulicic 0:c0ecb8bf28eb 19253 if (p != NULL) return p;
Marko Mikulicic 0:c0ecb8bf28eb 19254
Marko Mikulicic 0:c0ecb8bf28eb 19255 if (!v7_is_object(obj)) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19256 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19257 v7_own(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 19258 p = v7_mk_property(v7);
Marko Mikulicic 0:c0ecb8bf28eb 19259 v7_disown(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 19260
Marko Mikulicic 0:c0ecb8bf28eb 19261 p->attributes |= _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR | _V7_PROPERTY_HIDDEN;
Marko Mikulicic 0:c0ecb8bf28eb 19262
Marko Mikulicic 0:c0ecb8bf28eb 19263 p->next = o->properties;
Marko Mikulicic 0:c0ecb8bf28eb 19264 o->properties = p;
Marko Mikulicic 0:c0ecb8bf28eb 19265
Marko Mikulicic 0:c0ecb8bf28eb 19266 return p;
Marko Mikulicic 0:c0ecb8bf28eb 19267 }
Marko Mikulicic 0:c0ecb8bf28eb 19268
Marko Mikulicic 0:c0ecb8bf28eb 19269 void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud) {
Marko Mikulicic 0:c0ecb8bf28eb 19270 struct v7_property *p = get_or_create_user_data_property(v7, obj);
Marko Mikulicic 0:c0ecb8bf28eb 19271 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 19272 p->value = v7_mk_foreign(v7, ud);
Marko Mikulicic 0:c0ecb8bf28eb 19273 }
Marko Mikulicic 0:c0ecb8bf28eb 19274
Marko Mikulicic 0:c0ecb8bf28eb 19275 void *v7_get_user_data(struct v7 *v7, v7_val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19276 struct v7_property *p = get_user_data_property(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19277 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19278 if (p == NULL) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19279 return v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 19280 }
Marko Mikulicic 0:c0ecb8bf28eb 19281
Marko Mikulicic 0:c0ecb8bf28eb 19282 void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d) {
Marko Mikulicic 0:c0ecb8bf28eb 19283 struct v7_property *p = get_or_create_user_data_property(v7, obj);
Marko Mikulicic 0:c0ecb8bf28eb 19284 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 19285 union {
Marko Mikulicic 0:c0ecb8bf28eb 19286 void *v;
Marko Mikulicic 0:c0ecb8bf28eb 19287 v7_destructor_cb_t *f;
Marko Mikulicic 0:c0ecb8bf28eb 19288 } fu;
Marko Mikulicic 0:c0ecb8bf28eb 19289
Marko Mikulicic 0:c0ecb8bf28eb 19290 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 19291
Marko Mikulicic 0:c0ecb8bf28eb 19292 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19293 if (d != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19294 o->attributes |= V7_OBJ_HAS_DESTRUCTOR;
Marko Mikulicic 0:c0ecb8bf28eb 19295 fu.f = d;
Marko Mikulicic 0:c0ecb8bf28eb 19296 p->name = v7_mk_foreign(v7, fu.v);
Marko Mikulicic 0:c0ecb8bf28eb 19297 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19298 o->attributes &= ~V7_OBJ_HAS_DESTRUCTOR;
Marko Mikulicic 0:c0ecb8bf28eb 19299 p->name = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19300 }
Marko Mikulicic 0:c0ecb8bf28eb 19301 }
Marko Mikulicic 0:c0ecb8bf28eb 19302
Marko Mikulicic 0:c0ecb8bf28eb 19303 /* }}} Object prototypes */
Marko Mikulicic 0:c0ecb8bf28eb 19304 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 19305 #line 1 "v7/src/regexp.c"
Marko Mikulicic 0:c0ecb8bf28eb 19306 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19307 /*
Marko Mikulicic 0:c0ecb8bf28eb 19308 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 19309 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 19310 */
Marko Mikulicic 0:c0ecb8bf28eb 19311
Marko Mikulicic 0:c0ecb8bf28eb 19312 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19313 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19314 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19315 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19316 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19317 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19318 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19319 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19320
Marko Mikulicic 0:c0ecb8bf28eb 19321 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 19322 enum v7_err v7_mk_regexp(struct v7 *v7, const char *re, size_t re_len,
Marko Mikulicic 0:c0ecb8bf28eb 19323 const char *flags, size_t flags_len, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19324 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19325 struct slre_prog *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19326 struct v7_regexp *rp;
Marko Mikulicic 0:c0ecb8bf28eb 19327
Marko Mikulicic 0:c0ecb8bf28eb 19328 if (re_len == ~((size_t) 0)) re_len = strlen(re);
Marko Mikulicic 0:c0ecb8bf28eb 19329
Marko Mikulicic 0:c0ecb8bf28eb 19330 if (slre_compile(re, re_len, flags, flags_len, &p, 1) != SLRE_OK ||
Marko Mikulicic 0:c0ecb8bf28eb 19331 p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19332 rcode = v7_throwf(v7, TYPE_ERROR, "Invalid regex");
Marko Mikulicic 0:c0ecb8bf28eb 19333 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19334 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19335 *res = mk_object(v7, v7->vals.regexp_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 19336 rp = (struct v7_regexp *) malloc(sizeof(*rp));
Marko Mikulicic 0:c0ecb8bf28eb 19337 rp->regexp_string = v7_mk_string(v7, re, re_len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 19338 v7_own(v7, &rp->regexp_string);
Marko Mikulicic 0:c0ecb8bf28eb 19339 rp->compiled_regexp = p;
Marko Mikulicic 0:c0ecb8bf28eb 19340 rp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19341
Marko Mikulicic 0:c0ecb8bf28eb 19342 v7_def(v7, *res, "", 0, _V7_DESC_HIDDEN(1),
Marko Mikulicic 0:c0ecb8bf28eb 19343 pointer_to_value(rp) | V7_TAG_REGEXP);
Marko Mikulicic 0:c0ecb8bf28eb 19344 }
Marko Mikulicic 0:c0ecb8bf28eb 19345
Marko Mikulicic 0:c0ecb8bf28eb 19346 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19347 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19348 }
Marko Mikulicic 0:c0ecb8bf28eb 19349
Marko Mikulicic 0:c0ecb8bf28eb 19350 V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 19351 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 19352 int is = v7_is_regexp(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 19353 (void) is;
Marko Mikulicic 0:c0ecb8bf28eb 19354 assert(is == 1);
Marko Mikulicic 0:c0ecb8bf28eb 19355 /* TODO(mkm): make regexp use user data API */
Marko Mikulicic 0:c0ecb8bf28eb 19356 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 19357 assert(p != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 19358 return (struct v7_regexp *) get_ptr(p->value);
Marko Mikulicic 0:c0ecb8bf28eb 19359 }
Marko Mikulicic 0:c0ecb8bf28eb 19360
Marko Mikulicic 0:c0ecb8bf28eb 19361 int v7_is_regexp(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 19362 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 19363 if (!v7_is_generic_object(v)) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19364 /* TODO(mkm): make regexp use user data API */
Marko Mikulicic 0:c0ecb8bf28eb 19365 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 19366 if (p == NULL) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19367 return (p->value & V7_TAG_MASK) == V7_TAG_REGEXP;
Marko Mikulicic 0:c0ecb8bf28eb 19368 }
Marko Mikulicic 0:c0ecb8bf28eb 19369
Marko Mikulicic 0:c0ecb8bf28eb 19370 V7_PRIVATE size_t
Marko Mikulicic 0:c0ecb8bf28eb 19371 get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf) {
Marko Mikulicic 0:c0ecb8bf28eb 19372 int re_flags = slre_get_flags(rp->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 19373 size_t n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19374
Marko Mikulicic 0:c0ecb8bf28eb 19375 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19376 if (re_flags & SLRE_FLAG_G) buf[n++] = 'g';
Marko Mikulicic 0:c0ecb8bf28eb 19377 if (re_flags & SLRE_FLAG_I) buf[n++] = 'i';
Marko Mikulicic 0:c0ecb8bf28eb 19378 if (re_flags & SLRE_FLAG_M) buf[n++] = 'm';
Marko Mikulicic 0:c0ecb8bf28eb 19379
Marko Mikulicic 0:c0ecb8bf28eb 19380 assert(n <= _V7_REGEXP_MAX_FLAGS_LEN);
Marko Mikulicic 0:c0ecb8bf28eb 19381
Marko Mikulicic 0:c0ecb8bf28eb 19382 return n;
Marko Mikulicic 0:c0ecb8bf28eb 19383 }
Marko Mikulicic 0:c0ecb8bf28eb 19384
Marko Mikulicic 0:c0ecb8bf28eb 19385 #else /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 19386
Marko Mikulicic 0:c0ecb8bf28eb 19387 /*
Marko Mikulicic 0:c0ecb8bf28eb 19388 * Dummy implementation when RegExp support is disabled: just return 0
Marko Mikulicic 0:c0ecb8bf28eb 19389 */
Marko Mikulicic 0:c0ecb8bf28eb 19390 int v7_is_regexp(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 19391 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19392 (void) v;
Marko Mikulicic 0:c0ecb8bf28eb 19393 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19394 }
Marko Mikulicic 0:c0ecb8bf28eb 19395
Marko Mikulicic 0:c0ecb8bf28eb 19396 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 19397 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 19398 #line 1 "v7/src/exceptions.c"
Marko Mikulicic 0:c0ecb8bf28eb 19399 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19400 /*
Marko Mikulicic 0:c0ecb8bf28eb 19401 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 19402 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 19403 */
Marko Mikulicic 0:c0ecb8bf28eb 19404
Marko Mikulicic 0:c0ecb8bf28eb 19405 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19406 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19407 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19408 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19409 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19410 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19411 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19412
Marko Mikulicic 0:c0ecb8bf28eb 19413 enum v7_err v7_throw(struct v7 *v7, v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 19414 v7->vals.thrown_error = val;
Marko Mikulicic 0:c0ecb8bf28eb 19415 v7->is_thrown = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19416 return V7_EXEC_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 19417 }
Marko Mikulicic 0:c0ecb8bf28eb 19418
Marko Mikulicic 0:c0ecb8bf28eb 19419 void v7_clear_thrown_value(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 19420 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19421 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19422 }
Marko Mikulicic 0:c0ecb8bf28eb 19423
Marko Mikulicic 0:c0ecb8bf28eb 19424 enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt,
Marko Mikulicic 0:c0ecb8bf28eb 19425 ...) {
Marko Mikulicic 0:c0ecb8bf28eb 19426 /* TODO(dfrank) : get rid of v7->error_msg, allocate mem right here */
Marko Mikulicic 0:c0ecb8bf28eb 19427 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19428 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 19429 val_t e = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19430 va_start(ap, err_fmt);
Marko Mikulicic 0:c0ecb8bf28eb 19431 c_vsnprintf(v7->error_msg, sizeof(v7->error_msg), err_fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 19432 va_end(ap);
Marko Mikulicic 0:c0ecb8bf28eb 19433
Marko Mikulicic 0:c0ecb8bf28eb 19434 v7_own(v7, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19435 rcode = create_exception(v7, typ, v7->error_msg, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19436 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19437 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19438 }
Marko Mikulicic 0:c0ecb8bf28eb 19439
Marko Mikulicic 0:c0ecb8bf28eb 19440 rcode = v7_throw(v7, e);
Marko Mikulicic 0:c0ecb8bf28eb 19441
Marko Mikulicic 0:c0ecb8bf28eb 19442 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19443 v7_disown(v7, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19444 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19445 }
Marko Mikulicic 0:c0ecb8bf28eb 19446
Marko Mikulicic 0:c0ecb8bf28eb 19447 enum v7_err v7_rethrow(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 19448 assert(v7->is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 19449 #ifdef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 19450 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19451 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19452 return V7_EXEC_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 19453 }
Marko Mikulicic 0:c0ecb8bf28eb 19454
Marko Mikulicic 0:c0ecb8bf28eb 19455 v7_val_t v7_get_thrown_value(struct v7 *v7, uint8_t *is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 19456 if (is_thrown != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19457 *is_thrown = v7->is_thrown;
Marko Mikulicic 0:c0ecb8bf28eb 19458 }
Marko Mikulicic 0:c0ecb8bf28eb 19459 return v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 19460 }
Marko Mikulicic 0:c0ecb8bf28eb 19461
Marko Mikulicic 0:c0ecb8bf28eb 19462 /*
Marko Mikulicic 0:c0ecb8bf28eb 19463 * Create an instance of the exception with type `typ` (see `TYPE_ERROR`,
Marko Mikulicic 0:c0ecb8bf28eb 19464 * `SYNTAX_ERROR`, etc) and message `msg`.
Marko Mikulicic 0:c0ecb8bf28eb 19465 */
Marko Mikulicic 0:c0ecb8bf28eb 19466 V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ,
Marko Mikulicic 0:c0ecb8bf28eb 19467 const char *msg, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19468 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19469 uint8_t saved_creating_exception = v7->creating_exception;
Marko Mikulicic 0:c0ecb8bf28eb 19470 val_t ctor_args = V7_UNDEFINED, ctor_func = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19471 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 19472 assert(v7_is_undefined(v7->vals.thrown_error));
Marko Mikulicic 0:c0ecb8bf28eb 19473 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19474
Marko Mikulicic 0:c0ecb8bf28eb 19475 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19476
Marko Mikulicic 0:c0ecb8bf28eb 19477 v7_own(v7, &ctor_args);
Marko Mikulicic 0:c0ecb8bf28eb 19478 v7_own(v7, &ctor_func);
Marko Mikulicic 0:c0ecb8bf28eb 19479
Marko Mikulicic 0:c0ecb8bf28eb 19480 if (v7->creating_exception) {
Marko Mikulicic 0:c0ecb8bf28eb 19481 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 19482 fprintf(stderr, "Exception creation throws an exception %s: %s\n", typ,
Marko Mikulicic 0:c0ecb8bf28eb 19483 msg);
Marko Mikulicic 0:c0ecb8bf28eb 19484 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19485 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19486 v7->creating_exception = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19487
Marko Mikulicic 0:c0ecb8bf28eb 19488 /* Prepare arguments for the `Error` constructor */
Marko Mikulicic 0:c0ecb8bf28eb 19489 ctor_args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 19490 v7_array_set(v7, ctor_args, 0, v7_mk_string(v7, msg, strlen(msg), 1));
Marko Mikulicic 0:c0ecb8bf28eb 19491
Marko Mikulicic 0:c0ecb8bf28eb 19492 /* Get constructor for the given error `typ` */
Marko Mikulicic 0:c0ecb8bf28eb 19493 ctor_func = v7_get(v7, v7->vals.global_object, typ, ~0);
Marko Mikulicic 0:c0ecb8bf28eb 19494 if (v7_is_undefined(ctor_func)) {
Marko Mikulicic 0:c0ecb8bf28eb 19495 fprintf(stderr, "cannot find exception %s\n", typ);
Marko Mikulicic 0:c0ecb8bf28eb 19496 }
Marko Mikulicic 0:c0ecb8bf28eb 19497
Marko Mikulicic 0:c0ecb8bf28eb 19498 /* Create an error object, with prototype from constructor function */
Marko Mikulicic 0:c0ecb8bf28eb 19499 *res = mk_object(v7, v7_get(v7, ctor_func, "prototype", 9));
Marko Mikulicic 0:c0ecb8bf28eb 19500
Marko Mikulicic 0:c0ecb8bf28eb 19501 /*
Marko Mikulicic 0:c0ecb8bf28eb 19502 * Finally, call the error constructor, passing an error object as `this`
Marko Mikulicic 0:c0ecb8bf28eb 19503 */
Marko Mikulicic 0:c0ecb8bf28eb 19504 V7_TRY(b_apply(v7, ctor_func, *res, ctor_args, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 19505 }
Marko Mikulicic 0:c0ecb8bf28eb 19506
Marko Mikulicic 0:c0ecb8bf28eb 19507 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19508 v7->creating_exception = saved_creating_exception;
Marko Mikulicic 0:c0ecb8bf28eb 19509
Marko Mikulicic 0:c0ecb8bf28eb 19510 v7_disown(v7, &ctor_func);
Marko Mikulicic 0:c0ecb8bf28eb 19511 v7_disown(v7, &ctor_args);
Marko Mikulicic 0:c0ecb8bf28eb 19512
Marko Mikulicic 0:c0ecb8bf28eb 19513 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19514 }
Marko Mikulicic 0:c0ecb8bf28eb 19515 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 19516 #line 1 "v7/src/conversion.c"
Marko Mikulicic 0:c0ecb8bf28eb 19517 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19518 /*
Marko Mikulicic 0:c0ecb8bf28eb 19519 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 19520 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 19521 */
Marko Mikulicic 0:c0ecb8bf28eb 19522
Marko Mikulicic 0:c0ecb8bf28eb 19523 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19524 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19525
Marko Mikulicic 0:c0ecb8bf28eb 19526 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19527 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19528 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19529 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19530 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19531 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19532 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19533 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19534 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19535 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19536 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19537
Marko Mikulicic 0:c0ecb8bf28eb 19538 static void save_val(struct v7 *v7, const char *str, size_t str_len,
Marko Mikulicic 0:c0ecb8bf28eb 19539 val_t *dst_v, char *dst, size_t dst_size, int wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19540 size_t *res_wanted_len) {
Marko Mikulicic 0:c0ecb8bf28eb 19541 if (dst_v != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19542 *dst_v = v7_mk_string(v7, str, str_len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 19543 }
Marko Mikulicic 0:c0ecb8bf28eb 19544
Marko Mikulicic 0:c0ecb8bf28eb 19545 if (dst != NULL && dst_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 19546 size_t size = str_len + 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 19547 if (size > dst_size) {
Marko Mikulicic 0:c0ecb8bf28eb 19548 size = dst_size;
Marko Mikulicic 0:c0ecb8bf28eb 19549 }
Marko Mikulicic 0:c0ecb8bf28eb 19550 memcpy(dst, str, size);
Marko Mikulicic 0:c0ecb8bf28eb 19551
Marko Mikulicic 0:c0ecb8bf28eb 19552 /* make sure we have null-term */
Marko Mikulicic 0:c0ecb8bf28eb 19553 dst[dst_size - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 19554 }
Marko Mikulicic 0:c0ecb8bf28eb 19555
Marko Mikulicic 0:c0ecb8bf28eb 19556 if (res_wanted_len != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19557 *res_wanted_len = (wanted_len >= 0) ? (size_t) wanted_len : str_len;
Marko Mikulicic 0:c0ecb8bf28eb 19558 }
Marko Mikulicic 0:c0ecb8bf28eb 19559 }
Marko Mikulicic 0:c0ecb8bf28eb 19560
Marko Mikulicic 0:c0ecb8bf28eb 19561 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19562 V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 19563 char *buf, size_t buf_size,
Marko Mikulicic 0:c0ecb8bf28eb 19564 size_t *res_len) {
Marko Mikulicic 0:c0ecb8bf28eb 19565 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19566 char tmp_buf[25];
Marko Mikulicic 0:c0ecb8bf28eb 19567 double num;
Marko Mikulicic 0:c0ecb8bf28eb 19568 size_t wanted_len;
Marko Mikulicic 0:c0ecb8bf28eb 19569
Marko Mikulicic 0:c0ecb8bf28eb 19570 assert(!v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 19571
Marko Mikulicic 0:c0ecb8bf28eb 19572 memset(tmp_buf, 0x00, sizeof(tmp_buf));
Marko Mikulicic 0:c0ecb8bf28eb 19573
Marko Mikulicic 0:c0ecb8bf28eb 19574 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19575
Marko Mikulicic 0:c0ecb8bf28eb 19576 switch (val_type(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19577 case V7_TYPE_STRING: {
Marko Mikulicic 0:c0ecb8bf28eb 19578 /* if `res` provided, set it to source value */
Marko Mikulicic 0:c0ecb8bf28eb 19579 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19580 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19581 }
Marko Mikulicic 0:c0ecb8bf28eb 19582
Marko Mikulicic 0:c0ecb8bf28eb 19583 /* if buf provided, copy string data there */
Marko Mikulicic 0:c0ecb8bf28eb 19584 if (buf != NULL && buf_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 19585 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 19586 const char *str = v7_get_string(v7, &v, &size);
Marko Mikulicic 0:c0ecb8bf28eb 19587 size += 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 19588
Marko Mikulicic 0:c0ecb8bf28eb 19589 if (size > buf_size) {
Marko Mikulicic 0:c0ecb8bf28eb 19590 size = buf_size;
Marko Mikulicic 0:c0ecb8bf28eb 19591 }
Marko Mikulicic 0:c0ecb8bf28eb 19592
Marko Mikulicic 0:c0ecb8bf28eb 19593 memcpy(buf, str, size);
Marko Mikulicic 0:c0ecb8bf28eb 19594
Marko Mikulicic 0:c0ecb8bf28eb 19595 /* make sure we have a null-term */
Marko Mikulicic 0:c0ecb8bf28eb 19596 buf[buf_size - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 19597 }
Marko Mikulicic 0:c0ecb8bf28eb 19598
Marko Mikulicic 0:c0ecb8bf28eb 19599 if (res_len != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19600 v7_get_string(v7, &v, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19601 }
Marko Mikulicic 0:c0ecb8bf28eb 19602
Marko Mikulicic 0:c0ecb8bf28eb 19603 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19604 }
Marko Mikulicic 0:c0ecb8bf28eb 19605 case V7_TYPE_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 19606 strncpy(tmp_buf, "null", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19607 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19608 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19609 case V7_TYPE_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 19610 strncpy(tmp_buf, "undefined", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19611 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19612 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19613 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 19614 if (v7_get_bool(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19615 strncpy(tmp_buf, "true", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19616 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19617 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19618 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19619 strncpy(tmp_buf, "false", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19620 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19621 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19622 }
Marko Mikulicic 0:c0ecb8bf28eb 19623 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 19624 if (v == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 19625 strncpy(tmp_buf, "NaN", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19626 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19627 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19628 }
Marko Mikulicic 0:c0ecb8bf28eb 19629 num = v7_get_double(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 19630 if (isinf(num)) {
Marko Mikulicic 0:c0ecb8bf28eb 19631 if (num < 0.0) {
Marko Mikulicic 0:c0ecb8bf28eb 19632 strncpy(tmp_buf, "-Infinity", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19633 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19634 strncpy(tmp_buf, "Infinity", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19635 }
Marko Mikulicic 0:c0ecb8bf28eb 19636 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19637 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19638 }
Marko Mikulicic 0:c0ecb8bf28eb 19639 {
Marko Mikulicic 0:c0ecb8bf28eb 19640 const char *fmt = num > 1e10 ? "%.21g" : "%.10g";
Marko Mikulicic 0:c0ecb8bf28eb 19641 wanted_len = snprintf(tmp_buf, sizeof(tmp_buf), fmt, num);
Marko Mikulicic 0:c0ecb8bf28eb 19642 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19643 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19644 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19645 }
Marko Mikulicic 0:c0ecb8bf28eb 19646 case V7_TYPE_CFUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 19647 #ifdef V7_UNIT_TEST
Marko Mikulicic 0:c0ecb8bf28eb 19648 wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_xxxxxx");
Marko Mikulicic 0:c0ecb8bf28eb 19649 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19650 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19651 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19652 #else
Marko Mikulicic 0:c0ecb8bf28eb 19653 wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_%p", get_ptr(v));
Marko Mikulicic 0:c0ecb8bf28eb 19654 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19655 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19656 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19657 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19658 case V7_TYPE_FOREIGN:
Marko Mikulicic 0:c0ecb8bf28eb 19659 wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "[foreign_%p]",
Marko Mikulicic 0:c0ecb8bf28eb 19660 v7_get_ptr(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 19661 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19662 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19663 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19664 default:
Marko Mikulicic 0:c0ecb8bf28eb 19665 abort();
Marko Mikulicic 0:c0ecb8bf28eb 19666 }
Marko Mikulicic 0:c0ecb8bf28eb 19667
Marko Mikulicic 0:c0ecb8bf28eb 19668 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19669
Marko Mikulicic 0:c0ecb8bf28eb 19670 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19671 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19672 }
Marko Mikulicic 0:c0ecb8bf28eb 19673
Marko Mikulicic 0:c0ecb8bf28eb 19674 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19675 V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19676 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19677
Marko Mikulicic 0:c0ecb8bf28eb 19678 assert(!v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 19679
Marko Mikulicic 0:c0ecb8bf28eb 19680 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19681
Marko Mikulicic 0:c0ecb8bf28eb 19682 if (v7_is_number(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19683 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19684 }
Marko Mikulicic 0:c0ecb8bf28eb 19685
Marko Mikulicic 0:c0ecb8bf28eb 19686 if (v7_is_undefined(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19687 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 19688 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19689 }
Marko Mikulicic 0:c0ecb8bf28eb 19690
Marko Mikulicic 0:c0ecb8bf28eb 19691 if (v7_is_null(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19692 *res = v7_mk_number(v7, 0.0);
Marko Mikulicic 0:c0ecb8bf28eb 19693 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19694 }
Marko Mikulicic 0:c0ecb8bf28eb 19695
Marko Mikulicic 0:c0ecb8bf28eb 19696 if (v7_is_boolean(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19697 *res = v7_mk_number(v7, !!v7_get_bool(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 19698 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19699 }
Marko Mikulicic 0:c0ecb8bf28eb 19700
Marko Mikulicic 0:c0ecb8bf28eb 19701 if (is_cfunction_lite(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19702 *res = v7_mk_number(v7, 0.0);
Marko Mikulicic 0:c0ecb8bf28eb 19703 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19704 }
Marko Mikulicic 0:c0ecb8bf28eb 19705
Marko Mikulicic 0:c0ecb8bf28eb 19706 if (v7_is_string(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19707 double d;
Marko Mikulicic 0:c0ecb8bf28eb 19708 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 19709 char *e, *s = (char *) v7_get_string(v7, res, &n);
Marko Mikulicic 0:c0ecb8bf28eb 19710 if (n != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 19711 d = cs_strtod(s, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19712 if (e - n != s) {
Marko Mikulicic 0:c0ecb8bf28eb 19713 d = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 19714 }
Marko Mikulicic 0:c0ecb8bf28eb 19715 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19716 /* empty string: convert to 0 */
Marko Mikulicic 0:c0ecb8bf28eb 19717 d = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 19718 }
Marko Mikulicic 0:c0ecb8bf28eb 19719 *res = v7_mk_number(v7, d);
Marko Mikulicic 0:c0ecb8bf28eb 19720 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19721 }
Marko Mikulicic 0:c0ecb8bf28eb 19722
Marko Mikulicic 0:c0ecb8bf28eb 19723 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 19724
Marko Mikulicic 0:c0ecb8bf28eb 19725 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19726 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19727 }
Marko Mikulicic 0:c0ecb8bf28eb 19728
Marko Mikulicic 0:c0ecb8bf28eb 19729 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19730 enum v7_err to_primitive(struct v7 *v7, val_t v, enum to_primitive_hint hint,
Marko Mikulicic 0:c0ecb8bf28eb 19731 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19732 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19733 enum v7_err (*p_func)(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 19734
Marko Mikulicic 0:c0ecb8bf28eb 19735 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19736
Marko Mikulicic 0:c0ecb8bf28eb 19737 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19738
Marko Mikulicic 0:c0ecb8bf28eb 19739 /*
Marko Mikulicic 0:c0ecb8bf28eb 19740 * If given value is an object, try to convert it to string by calling first
Marko Mikulicic 0:c0ecb8bf28eb 19741 * preferred function (`toString()` or `valueOf()`, depending on the `hint`
Marko Mikulicic 0:c0ecb8bf28eb 19742 * argument)
Marko Mikulicic 0:c0ecb8bf28eb 19743 */
Marko Mikulicic 0:c0ecb8bf28eb 19744 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19745 /* Handle special case for Date object */
Marko Mikulicic 0:c0ecb8bf28eb 19746 if (hint == V7_TO_PRIMITIVE_HINT_AUTO) {
Marko Mikulicic 0:c0ecb8bf28eb 19747 hint = (v7_get_proto(v7, *res) == v7->vals.date_prototype)
Marko Mikulicic 0:c0ecb8bf28eb 19748 ? V7_TO_PRIMITIVE_HINT_STRING
Marko Mikulicic 0:c0ecb8bf28eb 19749 : V7_TO_PRIMITIVE_HINT_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 19750 }
Marko Mikulicic 0:c0ecb8bf28eb 19751
Marko Mikulicic 0:c0ecb8bf28eb 19752 p_func =
Marko Mikulicic 0:c0ecb8bf28eb 19753 (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_value_of : obj_to_string;
Marko Mikulicic 0:c0ecb8bf28eb 19754 rcode = p_func(v7, *res, res);
Marko Mikulicic 0:c0ecb8bf28eb 19755 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19756 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19757 }
Marko Mikulicic 0:c0ecb8bf28eb 19758
Marko Mikulicic 0:c0ecb8bf28eb 19759 /*
Marko Mikulicic 0:c0ecb8bf28eb 19760 * If returned value is still an object, get original argument value
Marko Mikulicic 0:c0ecb8bf28eb 19761 */
Marko Mikulicic 0:c0ecb8bf28eb 19762 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19763 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19764 }
Marko Mikulicic 0:c0ecb8bf28eb 19765 }
Marko Mikulicic 0:c0ecb8bf28eb 19766
Marko Mikulicic 0:c0ecb8bf28eb 19767 /*
Marko Mikulicic 0:c0ecb8bf28eb 19768 * If the value is still an object, try to call second function (`valueOf()`
Marko Mikulicic 0:c0ecb8bf28eb 19769 * or `toString()`)
Marko Mikulicic 0:c0ecb8bf28eb 19770 */
Marko Mikulicic 0:c0ecb8bf28eb 19771 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19772 p_func =
Marko Mikulicic 0:c0ecb8bf28eb 19773 (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_to_string : obj_value_of;
Marko Mikulicic 0:c0ecb8bf28eb 19774 rcode = p_func(v7, *res, res);
Marko Mikulicic 0:c0ecb8bf28eb 19775 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19776 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19777 }
Marko Mikulicic 0:c0ecb8bf28eb 19778 }
Marko Mikulicic 0:c0ecb8bf28eb 19779
Marko Mikulicic 0:c0ecb8bf28eb 19780 /*
Marko Mikulicic 0:c0ecb8bf28eb 19781 * If the value is still an object, then throw.
Marko Mikulicic 0:c0ecb8bf28eb 19782 */
Marko Mikulicic 0:c0ecb8bf28eb 19783 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19784 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 19785 v7_throwf(v7, TYPE_ERROR, "Cannot convert object to primitive value");
Marko Mikulicic 0:c0ecb8bf28eb 19786 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19787 }
Marko Mikulicic 0:c0ecb8bf28eb 19788
Marko Mikulicic 0:c0ecb8bf28eb 19789 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19790 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19791 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19792 }
Marko Mikulicic 0:c0ecb8bf28eb 19793
Marko Mikulicic 0:c0ecb8bf28eb 19794 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19795 V7_PRIVATE enum v7_err to_string(struct v7 *v7, val_t v, val_t *res, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 19796 size_t buf_size, size_t *res_len) {
Marko Mikulicic 0:c0ecb8bf28eb 19797 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19798
Marko Mikulicic 0:c0ecb8bf28eb 19799 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19800
Marko Mikulicic 0:c0ecb8bf28eb 19801 /*
Marko Mikulicic 0:c0ecb8bf28eb 19802 * Convert value to primitive if needed, calling `toString()` first
Marko Mikulicic 0:c0ecb8bf28eb 19803 */
Marko Mikulicic 0:c0ecb8bf28eb 19804 V7_TRY(to_primitive(v7, v, V7_TO_PRIMITIVE_HINT_STRING, &v));
Marko Mikulicic 0:c0ecb8bf28eb 19805
Marko Mikulicic 0:c0ecb8bf28eb 19806 /*
Marko Mikulicic 0:c0ecb8bf28eb 19807 * Now, we're guaranteed to have a primitive here. Convert it to string.
Marko Mikulicic 0:c0ecb8bf28eb 19808 */
Marko Mikulicic 0:c0ecb8bf28eb 19809 V7_TRY(primitive_to_str(v7, v, res, buf, buf_size, res_len));
Marko Mikulicic 0:c0ecb8bf28eb 19810
Marko Mikulicic 0:c0ecb8bf28eb 19811 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19812 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19813 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19814 }
Marko Mikulicic 0:c0ecb8bf28eb 19815
Marko Mikulicic 0:c0ecb8bf28eb 19816 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19817 V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19818 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19819
Marko Mikulicic 0:c0ecb8bf28eb 19820 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19821
Marko Mikulicic 0:c0ecb8bf28eb 19822 /*
Marko Mikulicic 0:c0ecb8bf28eb 19823 * Convert value to primitive if needed, calling `valueOf()` first
Marko Mikulicic 0:c0ecb8bf28eb 19824 */
Marko Mikulicic 0:c0ecb8bf28eb 19825 rcode = to_primitive(v7, *res, V7_TO_PRIMITIVE_HINT_NUMBER, res);
Marko Mikulicic 0:c0ecb8bf28eb 19826 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19827 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19828 }
Marko Mikulicic 0:c0ecb8bf28eb 19829
Marko Mikulicic 0:c0ecb8bf28eb 19830 /*
Marko Mikulicic 0:c0ecb8bf28eb 19831 * Now, we're guaranteed to have a primitive here. Convert it to number.
Marko Mikulicic 0:c0ecb8bf28eb 19832 */
Marko Mikulicic 0:c0ecb8bf28eb 19833 rcode = primitive_to_number(v7, *res, res);
Marko Mikulicic 0:c0ecb8bf28eb 19834 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19835 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19836 }
Marko Mikulicic 0:c0ecb8bf28eb 19837
Marko Mikulicic 0:c0ecb8bf28eb 19838 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19839 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19840 }
Marko Mikulicic 0:c0ecb8bf28eb 19841
Marko Mikulicic 0:c0ecb8bf28eb 19842 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19843 V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value,
Marko Mikulicic 0:c0ecb8bf28eb 19844 long *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19845 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19846 double d;
Marko Mikulicic 0:c0ecb8bf28eb 19847
Marko Mikulicic 0:c0ecb8bf28eb 19848 /* if value is `undefined`, just return `default_value` */
Marko Mikulicic 0:c0ecb8bf28eb 19849 if (v7_is_undefined(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19850 *res = default_value;
Marko Mikulicic 0:c0ecb8bf28eb 19851 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19852 }
Marko Mikulicic 0:c0ecb8bf28eb 19853
Marko Mikulicic 0:c0ecb8bf28eb 19854 /* Try to convert value to number */
Marko Mikulicic 0:c0ecb8bf28eb 19855 rcode = to_number_v(v7, v, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19856 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19857 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19858 }
Marko Mikulicic 0:c0ecb8bf28eb 19859
Marko Mikulicic 0:c0ecb8bf28eb 19860 /*
Marko Mikulicic 0:c0ecb8bf28eb 19861 * Conversion to number succeeded, so, convert it to long
Marko Mikulicic 0:c0ecb8bf28eb 19862 */
Marko Mikulicic 0:c0ecb8bf28eb 19863
Marko Mikulicic 0:c0ecb8bf28eb 19864 d = v7_get_double(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 19865 /* We want to return LONG_MAX if d is positive Inf, thus d < 0 check */
Marko Mikulicic 0:c0ecb8bf28eb 19866 if (isnan(d) || (isinf(d) && d < 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 19867 *res = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19868 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19869 } else if (d > LONG_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 19870 *res = LONG_MAX;
Marko Mikulicic 0:c0ecb8bf28eb 19871 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19872 }
Marko Mikulicic 0:c0ecb8bf28eb 19873 *res = (long) d;
Marko Mikulicic 0:c0ecb8bf28eb 19874 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19875
Marko Mikulicic 0:c0ecb8bf28eb 19876 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19877 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19878 }
Marko Mikulicic 0:c0ecb8bf28eb 19879
Marko Mikulicic 0:c0ecb8bf28eb 19880 V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19881 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19882 val_t func_valueOf = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19883
Marko Mikulicic 0:c0ecb8bf28eb 19884 v7_own(v7, &func_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 19885 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19886
Marko Mikulicic 0:c0ecb8bf28eb 19887 /*
Marko Mikulicic 0:c0ecb8bf28eb 19888 * TODO(dfrank): use `assert(v7_is_object(v))` instead, like `obj_to_string()`
Marko Mikulicic 0:c0ecb8bf28eb 19889 * does, and fix all callers to ensure it's an object before calling.
Marko Mikulicic 0:c0ecb8bf28eb 19890 *
Marko Mikulicic 0:c0ecb8bf28eb 19891 * Or, conversely, make `obj_to_string()` to accept objects.
Marko Mikulicic 0:c0ecb8bf28eb 19892 */
Marko Mikulicic 0:c0ecb8bf28eb 19893 if (!v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19894 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19895 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19896 }
Marko Mikulicic 0:c0ecb8bf28eb 19897
Marko Mikulicic 0:c0ecb8bf28eb 19898 V7_TRY(v7_get_throwing(v7, v, "valueOf", 7, &func_valueOf));
Marko Mikulicic 0:c0ecb8bf28eb 19899
Marko Mikulicic 0:c0ecb8bf28eb 19900 if (v7_is_callable(v7, func_valueOf)) {
Marko Mikulicic 0:c0ecb8bf28eb 19901 V7_TRY(b_apply(v7, func_valueOf, v, V7_UNDEFINED, 0, res));
Marko Mikulicic 0:c0ecb8bf28eb 19902 }
Marko Mikulicic 0:c0ecb8bf28eb 19903
Marko Mikulicic 0:c0ecb8bf28eb 19904 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19905 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19906 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19907 }
Marko Mikulicic 0:c0ecb8bf28eb 19908
Marko Mikulicic 0:c0ecb8bf28eb 19909 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19910 v7_disown(v7, &func_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 19911
Marko Mikulicic 0:c0ecb8bf28eb 19912 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19913 }
Marko Mikulicic 0:c0ecb8bf28eb 19914
Marko Mikulicic 0:c0ecb8bf28eb 19915 /*
Marko Mikulicic 0:c0ecb8bf28eb 19916 * Caller should ensure that `v` is an object
Marko Mikulicic 0:c0ecb8bf28eb 19917 */
Marko Mikulicic 0:c0ecb8bf28eb 19918 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19919 V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19920 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19921 val_t to_string_func = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19922
Marko Mikulicic 0:c0ecb8bf28eb 19923 /* Caller should ensure that `v` is an object */
Marko Mikulicic 0:c0ecb8bf28eb 19924 assert(v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 19925
Marko Mikulicic 0:c0ecb8bf28eb 19926 v7_own(v7, &to_string_func);
Marko Mikulicic 0:c0ecb8bf28eb 19927 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19928
Marko Mikulicic 0:c0ecb8bf28eb 19929 /*
Marko Mikulicic 0:c0ecb8bf28eb 19930 * If `toString` is callable, then call it; otherwise, just return source
Marko Mikulicic 0:c0ecb8bf28eb 19931 * value
Marko Mikulicic 0:c0ecb8bf28eb 19932 */
Marko Mikulicic 0:c0ecb8bf28eb 19933 V7_TRY(v7_get_throwing(v7, v, "toString", 8, &to_string_func));
Marko Mikulicic 0:c0ecb8bf28eb 19934 if (v7_is_callable(v7, to_string_func)) {
Marko Mikulicic 0:c0ecb8bf28eb 19935 V7_TRY(b_apply(v7, to_string_func, v, V7_UNDEFINED, 0, res));
Marko Mikulicic 0:c0ecb8bf28eb 19936 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19937 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19938 }
Marko Mikulicic 0:c0ecb8bf28eb 19939
Marko Mikulicic 0:c0ecb8bf28eb 19940 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19941 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19942 v7_disown(v7, &to_string_func);
Marko Mikulicic 0:c0ecb8bf28eb 19943
Marko Mikulicic 0:c0ecb8bf28eb 19944 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19945 }
Marko Mikulicic 0:c0ecb8bf28eb 19946
Marko Mikulicic 0:c0ecb8bf28eb 19947 static const char *hex_digits = "0123456789abcdef";
Marko Mikulicic 0:c0ecb8bf28eb 19948 static char *append_hex(char *buf, char *limit, uint8_t c) {
Marko Mikulicic 0:c0ecb8bf28eb 19949 if (buf < limit) *buf++ = 'u';
Marko Mikulicic 0:c0ecb8bf28eb 19950 if (buf < limit) *buf++ = '0';
Marko Mikulicic 0:c0ecb8bf28eb 19951 if (buf < limit) *buf++ = '0';
Marko Mikulicic 0:c0ecb8bf28eb 19952 if (buf < limit) *buf++ = hex_digits[(int) ((c >> 4) % 0xf)];
Marko Mikulicic 0:c0ecb8bf28eb 19953 if (buf < limit) *buf++ = hex_digits[(int) (c & 0xf)];
Marko Mikulicic 0:c0ecb8bf28eb 19954 return buf;
Marko Mikulicic 0:c0ecb8bf28eb 19955 }
Marko Mikulicic 0:c0ecb8bf28eb 19956
Marko Mikulicic 0:c0ecb8bf28eb 19957 /*
Marko Mikulicic 0:c0ecb8bf28eb 19958 * Appends quoted s to buf. Any double quote contained in s will be escaped.
Marko Mikulicic 0:c0ecb8bf28eb 19959 * Returns the number of characters that would have been added,
Marko Mikulicic 0:c0ecb8bf28eb 19960 * like snprintf.
Marko Mikulicic 0:c0ecb8bf28eb 19961 * If size is zero it doesn't output anything but keeps counting.
Marko Mikulicic 0:c0ecb8bf28eb 19962 */
Marko Mikulicic 0:c0ecb8bf28eb 19963 static int snquote(char *buf, size_t size, const char *s, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 19964 char *limit = buf + size - 1;
Marko Mikulicic 0:c0ecb8bf28eb 19965 const char *end;
Marko Mikulicic 0:c0ecb8bf28eb 19966 /*
Marko Mikulicic 0:c0ecb8bf28eb 19967 * String single character escape sequence:
Marko Mikulicic 0:c0ecb8bf28eb 19968 * http://www.ecma-international.org/ecma-262/6.0/index.html#table-34
Marko Mikulicic 0:c0ecb8bf28eb 19969 *
Marko Mikulicic 0:c0ecb8bf28eb 19970 * 0x8 -> \b
Marko Mikulicic 0:c0ecb8bf28eb 19971 * 0x9 -> \t
Marko Mikulicic 0:c0ecb8bf28eb 19972 * 0xa -> \n
Marko Mikulicic 0:c0ecb8bf28eb 19973 * 0xb -> \v
Marko Mikulicic 0:c0ecb8bf28eb 19974 * 0xc -> \f
Marko Mikulicic 0:c0ecb8bf28eb 19975 * 0xd -> \r
Marko Mikulicic 0:c0ecb8bf28eb 19976 */
Marko Mikulicic 0:c0ecb8bf28eb 19977 const char *specials = "btnvfr";
Marko Mikulicic 0:c0ecb8bf28eb 19978 size_t i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19979
Marko Mikulicic 0:c0ecb8bf28eb 19980 i++;
Marko Mikulicic 0:c0ecb8bf28eb 19981 if (buf < limit) *buf++ = '"';
Marko Mikulicic 0:c0ecb8bf28eb 19982
Marko Mikulicic 0:c0ecb8bf28eb 19983 for (end = s + len; s < end; s++) {
Marko Mikulicic 0:c0ecb8bf28eb 19984 if (*s == '"' || *s == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 19985 i++;
Marko Mikulicic 0:c0ecb8bf28eb 19986 if (buf < limit) *buf++ = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 19987 } else if (*s >= '\b' && *s <= '\r') {
Marko Mikulicic 0:c0ecb8bf28eb 19988 i += 2;
Marko Mikulicic 0:c0ecb8bf28eb 19989 if (buf < limit) *buf++ = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 19990 if (buf < limit) *buf++ = specials[*s - '\b'];
Marko Mikulicic 0:c0ecb8bf28eb 19991 continue;
Marko Mikulicic 0:c0ecb8bf28eb 19992 } else if ((unsigned char) *s < '\b' || (*s > '\r' && *s < ' ')) {
Marko Mikulicic 0:c0ecb8bf28eb 19993 i += 6 /* \uXXXX */;
Marko Mikulicic 0:c0ecb8bf28eb 19994 if (buf < limit) *buf++ = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 19995 buf = append_hex(buf, limit, (uint8_t) *s);
Marko Mikulicic 0:c0ecb8bf28eb 19996 continue;
Marko Mikulicic 0:c0ecb8bf28eb 19997 }
Marko Mikulicic 0:c0ecb8bf28eb 19998 i++;
Marko Mikulicic 0:c0ecb8bf28eb 19999 if (buf < limit) *buf++ = *s;
Marko Mikulicic 0:c0ecb8bf28eb 20000 }
Marko Mikulicic 0:c0ecb8bf28eb 20001
Marko Mikulicic 0:c0ecb8bf28eb 20002 i++;
Marko Mikulicic 0:c0ecb8bf28eb 20003 if (buf < limit) *buf++ = '"';
Marko Mikulicic 0:c0ecb8bf28eb 20004
Marko Mikulicic 0:c0ecb8bf28eb 20005 if (size != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 20006 *buf = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 20007 }
Marko Mikulicic 0:c0ecb8bf28eb 20008 return i;
Marko Mikulicic 0:c0ecb8bf28eb 20009 }
Marko Mikulicic 0:c0ecb8bf28eb 20010
Marko Mikulicic 0:c0ecb8bf28eb 20011 /*
Marko Mikulicic 0:c0ecb8bf28eb 20012 * Returns whether the value of given type should be skipped when generating
Marko Mikulicic 0:c0ecb8bf28eb 20013 * JSON output
Marko Mikulicic 0:c0ecb8bf28eb 20014 */
Marko Mikulicic 0:c0ecb8bf28eb 20015 static int should_skip_for_json(enum v7_type type) {
Marko Mikulicic 0:c0ecb8bf28eb 20016 int ret;
Marko Mikulicic 0:c0ecb8bf28eb 20017 switch (type) {
Marko Mikulicic 0:c0ecb8bf28eb 20018 /* All permitted values */
Marko Mikulicic 0:c0ecb8bf28eb 20019 case V7_TYPE_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 20020 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 20021 case V7_TYPE_BOOLEAN_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20022 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 20023 case V7_TYPE_NUMBER_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20024 case V7_TYPE_STRING:
Marko Mikulicic 0:c0ecb8bf28eb 20025 case V7_TYPE_STRING_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20026 case V7_TYPE_GENERIC_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20027 case V7_TYPE_ARRAY_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20028 case V7_TYPE_DATE_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20029 case V7_TYPE_REGEXP_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20030 case V7_TYPE_ERROR_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20031 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20032 break;
Marko Mikulicic 0:c0ecb8bf28eb 20033 default:
Marko Mikulicic 0:c0ecb8bf28eb 20034 ret = 1;
Marko Mikulicic 0:c0ecb8bf28eb 20035 break;
Marko Mikulicic 0:c0ecb8bf28eb 20036 }
Marko Mikulicic 0:c0ecb8bf28eb 20037 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 20038 }
Marko Mikulicic 0:c0ecb8bf28eb 20039
Marko Mikulicic 0:c0ecb8bf28eb 20040 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 20041 V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 20042 size_t size, size_t *res_len,
Marko Mikulicic 0:c0ecb8bf28eb 20043 uint8_t is_debug) {
Marko Mikulicic 0:c0ecb8bf28eb 20044 val_t el;
Marko Mikulicic 0:c0ecb8bf28eb 20045 char *vp;
Marko Mikulicic 0:c0ecb8bf28eb 20046 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 20047 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20048 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20049
Marko Mikulicic 0:c0ecb8bf28eb 20050 tmp_stack_push(&tf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 20051 tmp_stack_push(&tf, &el);
Marko Mikulicic 0:c0ecb8bf28eb 20052 /*
Marko Mikulicic 0:c0ecb8bf28eb 20053 * TODO(dfrank) : also push all `v7_val_t`s that are declared below
Marko Mikulicic 0:c0ecb8bf28eb 20054 */
Marko Mikulicic 0:c0ecb8bf28eb 20055
Marko Mikulicic 0:c0ecb8bf28eb 20056 if (size > 0) *buf = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 20057
Marko Mikulicic 0:c0ecb8bf28eb 20058 if (!is_debug && should_skip_for_json(val_type(v7, v))) {
Marko Mikulicic 0:c0ecb8bf28eb 20059 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20060 }
Marko Mikulicic 0:c0ecb8bf28eb 20061
Marko Mikulicic 0:c0ecb8bf28eb 20062 for (vp = v7->json_visited_stack.buf;
Marko Mikulicic 0:c0ecb8bf28eb 20063 vp < v7->json_visited_stack.buf + v7->json_visited_stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 20064 vp += sizeof(val_t)) {
Marko Mikulicic 0:c0ecb8bf28eb 20065 if (*(val_t *) vp == v) {
Marko Mikulicic 0:c0ecb8bf28eb 20066 strncpy(buf, "[Circular]", size);
Marko Mikulicic 0:c0ecb8bf28eb 20067 len = 10;
Marko Mikulicic 0:c0ecb8bf28eb 20068 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20069 }
Marko Mikulicic 0:c0ecb8bf28eb 20070 }
Marko Mikulicic 0:c0ecb8bf28eb 20071
Marko Mikulicic 0:c0ecb8bf28eb 20072 switch (val_type(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20073 case V7_TYPE_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 20074 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 20075 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 20076 case V7_TYPE_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 20077 case V7_TYPE_CFUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 20078 case V7_TYPE_FOREIGN:
Marko Mikulicic 0:c0ecb8bf28eb 20079 /* For those types, regular `primitive_to_str()` works */
Marko Mikulicic 0:c0ecb8bf28eb 20080 V7_TRY(primitive_to_str(v7, v, NULL, buf, size, &len));
Marko Mikulicic 0:c0ecb8bf28eb 20081 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20082
Marko Mikulicic 0:c0ecb8bf28eb 20083 case V7_TYPE_STRING: {
Marko Mikulicic 0:c0ecb8bf28eb 20084 /*
Marko Mikulicic 0:c0ecb8bf28eb 20085 * For strings we can't just use `primitive_to_str()`, because we need
Marko Mikulicic 0:c0ecb8bf28eb 20086 * quoted value
Marko Mikulicic 0:c0ecb8bf28eb 20087 */
Marko Mikulicic 0:c0ecb8bf28eb 20088 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 20089 const char *str = v7_get_string(v7, &v, &n);
Marko Mikulicic 0:c0ecb8bf28eb 20090 len = snquote(buf, size, str, n);
Marko Mikulicic 0:c0ecb8bf28eb 20091 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20092 }
Marko Mikulicic 0:c0ecb8bf28eb 20093
Marko Mikulicic 0:c0ecb8bf28eb 20094 case V7_TYPE_DATE_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 20095 v7_val_t func = V7_UNDEFINED, val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 20096 V7_TRY(v7_get_throwing(v7, v, "toString", 8, &func));
Marko Mikulicic 0:c0ecb8bf28eb 20097 #if V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 20098 if (!is_debug) {
Marko Mikulicic 0:c0ecb8bf28eb 20099 V7_TRY(v7_get_throwing(v7, v, "toJSON", 6, &func));
Marko Mikulicic 0:c0ecb8bf28eb 20100 }
Marko Mikulicic 0:c0ecb8bf28eb 20101 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20102 V7_TRY(b_apply(v7, func, v, V7_UNDEFINED, 0, &val));
Marko Mikulicic 0:c0ecb8bf28eb 20103 V7_TRY(to_json_or_debug(v7, val, buf, size, &len, is_debug));
Marko Mikulicic 0:c0ecb8bf28eb 20104 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20105 }
Marko Mikulicic 0:c0ecb8bf28eb 20106 case V7_TYPE_GENERIC_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20107 case V7_TYPE_BOOLEAN_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20108 case V7_TYPE_STRING_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20109 case V7_TYPE_NUMBER_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20110 case V7_TYPE_REGEXP_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20111 case V7_TYPE_ERROR_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 20112 /* TODO(imax): make it return the desired size of the buffer */
Marko Mikulicic 0:c0ecb8bf28eb 20113 char *b = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20114 v7_val_t name = V7_UNDEFINED, val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 20115 v7_prop_attr_t attrs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20116 const char *pname;
Marko Mikulicic 0:c0ecb8bf28eb 20117 size_t nlen;
Marko Mikulicic 0:c0ecb8bf28eb 20118 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20119 struct prop_iter_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 20120 memset(&ctx, 0, sizeof(ctx));
Marko Mikulicic 0:c0ecb8bf28eb 20121
Marko Mikulicic 0:c0ecb8bf28eb 20122 mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 20123 b += c_snprintf(b, BUF_LEFT(size, b - buf), "{");
Marko Mikulicic 0:c0ecb8bf28eb 20124 V7_TRY2(init_prop_iter_ctx(v7, v, 1 /*proxy-transparent*/, &ctx),
Marko Mikulicic 0:c0ecb8bf28eb 20125 clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 20126 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 20127 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 20128 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 20129 V7_TRY2(next_prop(v7, &ctx, &name, &val, &attrs, &ok), clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 20130 if (!ok) {
Marko Mikulicic 0:c0ecb8bf28eb 20131 break;
Marko Mikulicic 0:c0ecb8bf28eb 20132 } else if (attrs & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 20133 continue;
Marko Mikulicic 0:c0ecb8bf28eb 20134 }
Marko Mikulicic 0:c0ecb8bf28eb 20135 pname = v7_get_string(v7, &name, &nlen);
Marko Mikulicic 0:c0ecb8bf28eb 20136 V7_TRY(v7_get_throwing(v7, v, pname, nlen, &val));
Marko Mikulicic 0:c0ecb8bf28eb 20137 if (!is_debug && should_skip_for_json(val_type(v7, val))) {
Marko Mikulicic 0:c0ecb8bf28eb 20138 continue;
Marko Mikulicic 0:c0ecb8bf28eb 20139 }
Marko Mikulicic 0:c0ecb8bf28eb 20140 if (b - buf != 1) { /* Not the first property to be printed */
Marko Mikulicic 0:c0ecb8bf28eb 20141 b += c_snprintf(b, BUF_LEFT(size, b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 20142 }
Marko Mikulicic 0:c0ecb8bf28eb 20143 s = v7_get_string(v7, &name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 20144 b += c_snprintf(b, BUF_LEFT(size, b - buf), "\"%.*s\":", (int) n, s);
Marko Mikulicic 0:c0ecb8bf28eb 20145 {
Marko Mikulicic 0:c0ecb8bf28eb 20146 size_t tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20147 V7_TRY2(to_json_or_debug(v7, val, b, BUF_LEFT(size, b - buf), &tmp,
Marko Mikulicic 0:c0ecb8bf28eb 20148 is_debug),
Marko Mikulicic 0:c0ecb8bf28eb 20149 clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 20150 b += tmp;
Marko Mikulicic 0:c0ecb8bf28eb 20151 }
Marko Mikulicic 0:c0ecb8bf28eb 20152 }
Marko Mikulicic 0:c0ecb8bf28eb 20153 b += c_snprintf(b, BUF_LEFT(size, b - buf), "}");
Marko Mikulicic 0:c0ecb8bf28eb 20154 v7->json_visited_stack.len -= sizeof(v);
Marko Mikulicic 0:c0ecb8bf28eb 20155
Marko Mikulicic 0:c0ecb8bf28eb 20156 clean_iter:
Marko Mikulicic 0:c0ecb8bf28eb 20157 v7_destruct_prop_iter_ctx(v7, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 20158
Marko Mikulicic 0:c0ecb8bf28eb 20159 len = b - buf;
Marko Mikulicic 0:c0ecb8bf28eb 20160 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20161 }
Marko Mikulicic 0:c0ecb8bf28eb 20162 case V7_TYPE_ARRAY_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 20163 int has;
Marko Mikulicic 0:c0ecb8bf28eb 20164 char *b = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20165 size_t i, alen = v7_array_length(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 20166 mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 20167 b += c_snprintf(b, BUF_LEFT(size, b - buf), "[");
Marko Mikulicic 0:c0ecb8bf28eb 20168 for (i = 0; i < alen; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 20169 el = v7_array_get2(v7, v, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 20170 if (has) {
Marko Mikulicic 0:c0ecb8bf28eb 20171 size_t tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20172 if (!is_debug && should_skip_for_json(val_type(v7, el))) {
Marko Mikulicic 0:c0ecb8bf28eb 20173 b += c_snprintf(b, BUF_LEFT(size, b - buf), "null");
Marko Mikulicic 0:c0ecb8bf28eb 20174 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20175 V7_TRY(to_json_or_debug(v7, el, b, BUF_LEFT(size, b - buf), &tmp,
Marko Mikulicic 0:c0ecb8bf28eb 20176 is_debug));
Marko Mikulicic 0:c0ecb8bf28eb 20177 }
Marko Mikulicic 0:c0ecb8bf28eb 20178 b += tmp;
Marko Mikulicic 0:c0ecb8bf28eb 20179 }
Marko Mikulicic 0:c0ecb8bf28eb 20180 if (i != alen - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 20181 b += c_snprintf(b, BUF_LEFT(size, b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 20182 }
Marko Mikulicic 0:c0ecb8bf28eb 20183 }
Marko Mikulicic 0:c0ecb8bf28eb 20184 b += c_snprintf(b, BUF_LEFT(size, b - buf), "]");
Marko Mikulicic 0:c0ecb8bf28eb 20185 v7->json_visited_stack.len -= sizeof(v);
Marko Mikulicic 0:c0ecb8bf28eb 20186 len = b - buf;
Marko Mikulicic 0:c0ecb8bf28eb 20187 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20188 }
Marko Mikulicic 0:c0ecb8bf28eb 20189 case V7_TYPE_CFUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20190 V7_TRY(obj_value_of(v7, v, &v));
Marko Mikulicic 0:c0ecb8bf28eb 20191 len = c_snprintf(buf, size, "Function cfunc_%p", get_ptr(v));
Marko Mikulicic 0:c0ecb8bf28eb 20192 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20193 case V7_TYPE_FUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20194 V7_TRY(to_string(v7, v, NULL, buf, size, &len));
Marko Mikulicic 0:c0ecb8bf28eb 20195 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20196
Marko Mikulicic 0:c0ecb8bf28eb 20197 case V7_TYPE_MAX_OBJECT_TYPE:
Marko Mikulicic 0:c0ecb8bf28eb 20198 case V7_NUM_TYPES:
Marko Mikulicic 0:c0ecb8bf28eb 20199 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20200 }
Marko Mikulicic 0:c0ecb8bf28eb 20201
Marko Mikulicic 0:c0ecb8bf28eb 20202 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20203
Marko Mikulicic 0:c0ecb8bf28eb 20204 len = 0; /* for compilers that don't know about abort() */
Marko Mikulicic 0:c0ecb8bf28eb 20205 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20206
Marko Mikulicic 0:c0ecb8bf28eb 20207 clean:
Marko Mikulicic 0:c0ecb8bf28eb 20208 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 20209 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20210 }
Marko Mikulicic 0:c0ecb8bf28eb 20211 if (res_len != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20212 *res_len = len;
Marko Mikulicic 0:c0ecb8bf28eb 20213 }
Marko Mikulicic 0:c0ecb8bf28eb 20214 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 20215 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 20216 }
Marko Mikulicic 0:c0ecb8bf28eb 20217
Marko Mikulicic 0:c0ecb8bf28eb 20218 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 20219 V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20220 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 20221 int is_truthy;
Marko Mikulicic 0:c0ecb8bf28eb 20222
Marko Mikulicic 0:c0ecb8bf28eb 20223 is_truthy = ((v7_is_boolean(v) && v7_get_bool(v7, v)) ||
Marko Mikulicic 0:c0ecb8bf28eb 20224 (v7_is_number(v) && v7_get_double(v7, v) != 0.0) ||
Marko Mikulicic 0:c0ecb8bf28eb 20225 (v7_is_string(v) && v7_get_string(v7, &v, &len) && len > 0) ||
Marko Mikulicic 0:c0ecb8bf28eb 20226 (v7_is_object(v))) &&
Marko Mikulicic 0:c0ecb8bf28eb 20227 v != V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 20228
Marko Mikulicic 0:c0ecb8bf28eb 20229 return v7_mk_boolean(v7, is_truthy);
Marko Mikulicic 0:c0ecb8bf28eb 20230 }
Marko Mikulicic 0:c0ecb8bf28eb 20231
Marko Mikulicic 0:c0ecb8bf28eb 20232 /*
Marko Mikulicic 0:c0ecb8bf28eb 20233 * v7_stringify allocates a new buffer if value representation doesn't fit into
Marko Mikulicic 0:c0ecb8bf28eb 20234 * buf. Caller is responsible for freeing that buffer.
Marko Mikulicic 0:c0ecb8bf28eb 20235 */
Marko Mikulicic 0:c0ecb8bf28eb 20236 char *v7_stringify(struct v7 *v7, val_t v, char *buf, size_t size,
Marko Mikulicic 0:c0ecb8bf28eb 20237 enum v7_stringify_mode mode) {
Marko Mikulicic 0:c0ecb8bf28eb 20238 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 20239 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20240 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 20241 char *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20242
Marko Mikulicic 0:c0ecb8bf28eb 20243 rcode = v7_stringify_throwing(v7, v, buf, size, mode, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 20244 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 20245 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 20246 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 20247 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 20248 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20249 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20250 }
Marko Mikulicic 0:c0ecb8bf28eb 20251
Marko Mikulicic 0:c0ecb8bf28eb 20252 buf[0] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 20253 ret = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20254 }
Marko Mikulicic 0:c0ecb8bf28eb 20255
Marko Mikulicic 0:c0ecb8bf28eb 20256 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 20257 }
Marko Mikulicic 0:c0ecb8bf28eb 20258
Marko Mikulicic 0:c0ecb8bf28eb 20259 enum v7_err v7_stringify_throwing(struct v7 *v7, val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 20260 size_t size, enum v7_stringify_mode mode,
Marko Mikulicic 0:c0ecb8bf28eb 20261 char **res) {
Marko Mikulicic 0:c0ecb8bf28eb 20262 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 20263 char *p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20264 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 20265
Marko Mikulicic 0:c0ecb8bf28eb 20266 switch (mode) {
Marko Mikulicic 0:c0ecb8bf28eb 20267 case V7_STRINGIFY_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 20268 V7_TRY(to_string(v7, v, NULL, buf, size, &len));
Marko Mikulicic 0:c0ecb8bf28eb 20269 break;
Marko Mikulicic 0:c0ecb8bf28eb 20270
Marko Mikulicic 0:c0ecb8bf28eb 20271 case V7_STRINGIFY_JSON:
Marko Mikulicic 0:c0ecb8bf28eb 20272 V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 0));
Marko Mikulicic 0:c0ecb8bf28eb 20273 break;
Marko Mikulicic 0:c0ecb8bf28eb 20274
Marko Mikulicic 0:c0ecb8bf28eb 20275 case V7_STRINGIFY_DEBUG:
Marko Mikulicic 0:c0ecb8bf28eb 20276 V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 1));
Marko Mikulicic 0:c0ecb8bf28eb 20277 break;
Marko Mikulicic 0:c0ecb8bf28eb 20278 }
Marko Mikulicic 0:c0ecb8bf28eb 20279
Marko Mikulicic 0:c0ecb8bf28eb 20280 /* fit null terminating byte */
Marko Mikulicic 0:c0ecb8bf28eb 20281 if (len >= size) {
Marko Mikulicic 0:c0ecb8bf28eb 20282 /* Buffer is not large enough. Allocate a bigger one */
Marko Mikulicic 0:c0ecb8bf28eb 20283 p = (char *) malloc(len + 1);
Marko Mikulicic 0:c0ecb8bf28eb 20284 V7_TRY(v7_stringify_throwing(v7, v, p, len + 1, mode, res));
Marko Mikulicic 0:c0ecb8bf28eb 20285 assert(*res == p);
Marko Mikulicic 0:c0ecb8bf28eb 20286 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20287 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20288 *res = p;
Marko Mikulicic 0:c0ecb8bf28eb 20289 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20290 }
Marko Mikulicic 0:c0ecb8bf28eb 20291
Marko Mikulicic 0:c0ecb8bf28eb 20292 clean:
Marko Mikulicic 0:c0ecb8bf28eb 20293 /*
Marko Mikulicic 0:c0ecb8bf28eb 20294 * If we're going to throw, and we allocated a buffer, then free it.
Marko Mikulicic 0:c0ecb8bf28eb 20295 * But if we don't throw, then the caller will free it.
Marko Mikulicic 0:c0ecb8bf28eb 20296 */
Marko Mikulicic 0:c0ecb8bf28eb 20297 if (rcode != V7_OK && p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 20298 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 20299 }
Marko Mikulicic 0:c0ecb8bf28eb 20300 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 20301 }
Marko Mikulicic 0:c0ecb8bf28eb 20302
Marko Mikulicic 0:c0ecb8bf28eb 20303 int v7_is_truthy(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20304 return v7_get_bool(v7, to_boolean_v(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 20305 }
Marko Mikulicic 0:c0ecb8bf28eb 20306 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 20307 #line 1 "v7/src/shdata.c"
Marko Mikulicic 0:c0ecb8bf28eb 20308 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20309 /*
Marko Mikulicic 0:c0ecb8bf28eb 20310 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 20311 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 20312 */
Marko Mikulicic 0:c0ecb8bf28eb 20313
Marko Mikulicic 0:c0ecb8bf28eb 20314 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20315 /* Amalgamated: #include "v7/src/shdata.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20316
Marko Mikulicic 0:c0ecb8bf28eb 20317 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 20318 V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 20319 struct shdata *ret =
Marko Mikulicic 0:c0ecb8bf28eb 20320 (struct shdata *) calloc(1, sizeof(struct shdata) + size);
Marko Mikulicic 0:c0ecb8bf28eb 20321 shdata_retain(ret);
Marko Mikulicic 0:c0ecb8bf28eb 20322 if (payload != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20323 memcpy((char *) shdata_get_payload(ret), (char *) payload, size);
Marko Mikulicic 0:c0ecb8bf28eb 20324 }
Marko Mikulicic 0:c0ecb8bf28eb 20325 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 20326 }
Marko Mikulicic 0:c0ecb8bf28eb 20327
Marko Mikulicic 0:c0ecb8bf28eb 20328 V7_PRIVATE struct shdata *shdata_create_from_string(const char *src) {
Marko Mikulicic 0:c0ecb8bf28eb 20329 return shdata_create(src, strlen(src) + 1 /*null-term*/);
Marko Mikulicic 0:c0ecb8bf28eb 20330 }
Marko Mikulicic 0:c0ecb8bf28eb 20331
Marko Mikulicic 0:c0ecb8bf28eb 20332 V7_PRIVATE void shdata_retain(struct shdata *p) {
Marko Mikulicic 0:c0ecb8bf28eb 20333 p->refcnt++;
Marko Mikulicic 0:c0ecb8bf28eb 20334 assert(p->refcnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 20335 }
Marko Mikulicic 0:c0ecb8bf28eb 20336
Marko Mikulicic 0:c0ecb8bf28eb 20337 V7_PRIVATE void shdata_release(struct shdata *p) {
Marko Mikulicic 0:c0ecb8bf28eb 20338 assert(p->refcnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 20339 p->refcnt--;
Marko Mikulicic 0:c0ecb8bf28eb 20340 if (p->refcnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 20341 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 20342 }
Marko Mikulicic 0:c0ecb8bf28eb 20343 }
Marko Mikulicic 0:c0ecb8bf28eb 20344
Marko Mikulicic 0:c0ecb8bf28eb 20345 V7_PRIVATE void *shdata_get_payload(struct shdata *p) {
Marko Mikulicic 0:c0ecb8bf28eb 20346 return (char *) p + sizeof(*p);
Marko Mikulicic 0:c0ecb8bf28eb 20347 }
Marko Mikulicic 0:c0ecb8bf28eb 20348 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20349 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 20350 #line 1 "v7/src/gc.c"
Marko Mikulicic 0:c0ecb8bf28eb 20351 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20352 /*
Marko Mikulicic 0:c0ecb8bf28eb 20353 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 20354 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 20355 */
Marko Mikulicic 0:c0ecb8bf28eb 20356
Marko Mikulicic 0:c0ecb8bf28eb 20357 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20358 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20359 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20360 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20361 /* Amalgamated: #include "v7/src/freeze.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20362 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20363 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20364 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20365 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20366 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20367 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20368 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20369 /* Amalgamated: #include "v7/src/heapusage.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20370
Marko Mikulicic 0:c0ecb8bf28eb 20371 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 20372
Marko Mikulicic 0:c0ecb8bf28eb 20373 #ifdef V7_STACK_GUARD_MIN_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 20374 void *v7_sp_limit = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20375 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20376
Marko Mikulicic 0:c0ecb8bf28eb 20377 void gc_mark_string(struct v7 *, val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 20378
Marko Mikulicic 0:c0ecb8bf28eb 20379 static struct gc_block *gc_new_block(struct gc_arena *a, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 20380 static void gc_free_block(struct gc_block *b);
Marko Mikulicic 0:c0ecb8bf28eb 20381 static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 20382 static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 20383 static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec);
Marko Mikulicic 0:c0ecb8bf28eb 20384
Marko Mikulicic 0:c0ecb8bf28eb 20385 V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20386 return (struct v7_generic_object *) gc_alloc_cell(v7,
Marko Mikulicic 0:c0ecb8bf28eb 20387 &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20388 }
Marko Mikulicic 0:c0ecb8bf28eb 20389
Marko Mikulicic 0:c0ecb8bf28eb 20390 V7_PRIVATE struct v7_property *new_property(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20391 return (struct v7_property *) gc_alloc_cell(v7, &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20392 }
Marko Mikulicic 0:c0ecb8bf28eb 20393
Marko Mikulicic 0:c0ecb8bf28eb 20394 V7_PRIVATE struct v7_js_function *new_function(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20395 return (struct v7_js_function *) gc_alloc_cell(v7, &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20396 }
Marko Mikulicic 0:c0ecb8bf28eb 20397
Marko Mikulicic 0:c0ecb8bf28eb 20398 V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20399 struct gc_tmp_frame frame;
Marko Mikulicic 0:c0ecb8bf28eb 20400 frame.v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 20401 frame.pos = v7->tmp_stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 20402 return frame;
Marko Mikulicic 0:c0ecb8bf28eb 20403 }
Marko Mikulicic 0:c0ecb8bf28eb 20404
Marko Mikulicic 0:c0ecb8bf28eb 20405 V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *tf) {
Marko Mikulicic 0:c0ecb8bf28eb 20406 tf->v7->tmp_stack.len = tf->pos;
Marko Mikulicic 0:c0ecb8bf28eb 20407 }
Marko Mikulicic 0:c0ecb8bf28eb 20408
Marko Mikulicic 0:c0ecb8bf28eb 20409 /*
Marko Mikulicic 0:c0ecb8bf28eb 20410 * TODO(mkm): perhaps it's safer to keep val_t in the temporary
Marko Mikulicic 0:c0ecb8bf28eb 20411 * roots stack, instead of keeping val_t*, in order to be better
Marko Mikulicic 0:c0ecb8bf28eb 20412 * able to debug the relocating GC.
Marko Mikulicic 0:c0ecb8bf28eb 20413 */
Marko Mikulicic 0:c0ecb8bf28eb 20414 V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *tf, val_t *vp) {
Marko Mikulicic 0:c0ecb8bf28eb 20415 mbuf_append(&tf->v7->tmp_stack, (char *) &vp, sizeof(val_t *));
Marko Mikulicic 0:c0ecb8bf28eb 20416 }
Marko Mikulicic 0:c0ecb8bf28eb 20417
Marko Mikulicic 0:c0ecb8bf28eb 20418 /* Initializes a new arena. */
Marko Mikulicic 0:c0ecb8bf28eb 20419 V7_PRIVATE void gc_arena_init(struct gc_arena *a, size_t cell_size,
Marko Mikulicic 0:c0ecb8bf28eb 20420 size_t initial_size, size_t size_increment,
Marko Mikulicic 0:c0ecb8bf28eb 20421 const char *name) {
Marko Mikulicic 0:c0ecb8bf28eb 20422 assert(cell_size >= sizeof(uintptr_t));
Marko Mikulicic 0:c0ecb8bf28eb 20423
Marko Mikulicic 0:c0ecb8bf28eb 20424 memset(a, 0, sizeof(*a));
Marko Mikulicic 0:c0ecb8bf28eb 20425 a->cell_size = cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20426 a->name = name;
Marko Mikulicic 0:c0ecb8bf28eb 20427 a->size_increment = size_increment;
Marko Mikulicic 0:c0ecb8bf28eb 20428 a->blocks = gc_new_block(a, initial_size);
Marko Mikulicic 0:c0ecb8bf28eb 20429 }
Marko Mikulicic 0:c0ecb8bf28eb 20430
Marko Mikulicic 0:c0ecb8bf28eb 20431 V7_PRIVATE void gc_arena_destroy(struct v7 *v7, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20432 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20433
Marko Mikulicic 0:c0ecb8bf28eb 20434 if (a->blocks != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20435 gc_sweep(v7, a, 0);
Marko Mikulicic 0:c0ecb8bf28eb 20436 for (b = a->blocks; b != NULL;) {
Marko Mikulicic 0:c0ecb8bf28eb 20437 struct gc_block *tmp;
Marko Mikulicic 0:c0ecb8bf28eb 20438 tmp = b;
Marko Mikulicic 0:c0ecb8bf28eb 20439 b = b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20440 gc_free_block(tmp);
Marko Mikulicic 0:c0ecb8bf28eb 20441 }
Marko Mikulicic 0:c0ecb8bf28eb 20442 }
Marko Mikulicic 0:c0ecb8bf28eb 20443 }
Marko Mikulicic 0:c0ecb8bf28eb 20444
Marko Mikulicic 0:c0ecb8bf28eb 20445 static void gc_free_block(struct gc_block *b) {
Marko Mikulicic 0:c0ecb8bf28eb 20446 free(b->base);
Marko Mikulicic 0:c0ecb8bf28eb 20447 free(b);
Marko Mikulicic 0:c0ecb8bf28eb 20448 }
Marko Mikulicic 0:c0ecb8bf28eb 20449
Marko Mikulicic 0:c0ecb8bf28eb 20450 static struct gc_block *gc_new_block(struct gc_arena *a, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 20451 struct gc_cell *cur;
Marko Mikulicic 0:c0ecb8bf28eb 20452 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20453
Marko Mikulicic 0:c0ecb8bf28eb 20454 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 20455 b = (struct gc_block *) calloc(1, sizeof(*b));
Marko Mikulicic 0:c0ecb8bf28eb 20456 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 20457 if (b == NULL) abort();
Marko Mikulicic 0:c0ecb8bf28eb 20458
Marko Mikulicic 0:c0ecb8bf28eb 20459 b->size = size;
Marko Mikulicic 0:c0ecb8bf28eb 20460 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 20461 b->base = (struct gc_cell *) calloc(a->cell_size, b->size);
Marko Mikulicic 0:c0ecb8bf28eb 20462 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 20463 if (b->base == NULL) abort();
Marko Mikulicic 0:c0ecb8bf28eb 20464
Marko Mikulicic 0:c0ecb8bf28eb 20465 for (cur = GC_CELL_OP(a, b->base, +, 0);
Marko Mikulicic 0:c0ecb8bf28eb 20466 cur < GC_CELL_OP(a, b->base, +, b->size);
Marko Mikulicic 0:c0ecb8bf28eb 20467 cur = GC_CELL_OP(a, cur, +, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 20468 cur->head.link = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20469 a->free = cur;
Marko Mikulicic 0:c0ecb8bf28eb 20470 }
Marko Mikulicic 0:c0ecb8bf28eb 20471
Marko Mikulicic 0:c0ecb8bf28eb 20472 return b;
Marko Mikulicic 0:c0ecb8bf28eb 20473 }
Marko Mikulicic 0:c0ecb8bf28eb 20474
Marko Mikulicic 0:c0ecb8bf28eb 20475 V7_PRIVATE void *gc_alloc_cell(struct v7 *v7, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20476 #if V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 20477 struct gc_cell *r;
Marko Mikulicic 0:c0ecb8bf28eb 20478 maybe_gc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20479 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 20480 r = (struct gc_cell *) calloc(1, a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 20481 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 20482 mbuf_append(&v7->malloc_trace, &r, sizeof(r));
Marko Mikulicic 0:c0ecb8bf28eb 20483 return r;
Marko Mikulicic 0:c0ecb8bf28eb 20484 #else
Marko Mikulicic 0:c0ecb8bf28eb 20485 struct gc_cell *r;
Marko Mikulicic 0:c0ecb8bf28eb 20486 if (a->free == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20487 if (!maybe_gc(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 20488 /* GC is inhibited, so, schedule invocation for later */
Marko Mikulicic 0:c0ecb8bf28eb 20489 v7->need_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 20490 }
Marko Mikulicic 0:c0ecb8bf28eb 20491
Marko Mikulicic 0:c0ecb8bf28eb 20492 if (a->free == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20493 struct gc_block *b = gc_new_block(a, a->size_increment);
Marko Mikulicic 0:c0ecb8bf28eb 20494 b->next = a->blocks;
Marko Mikulicic 0:c0ecb8bf28eb 20495 a->blocks = b;
Marko Mikulicic 0:c0ecb8bf28eb 20496 }
Marko Mikulicic 0:c0ecb8bf28eb 20497 }
Marko Mikulicic 0:c0ecb8bf28eb 20498 r = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20499
Marko Mikulicic 0:c0ecb8bf28eb 20500 UNMARK(r);
Marko Mikulicic 0:c0ecb8bf28eb 20501
Marko Mikulicic 0:c0ecb8bf28eb 20502 a->free = r->head.link;
Marko Mikulicic 0:c0ecb8bf28eb 20503
Marko Mikulicic 0:c0ecb8bf28eb 20504 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20505 a->allocations++;
Marko Mikulicic 0:c0ecb8bf28eb 20506 a->alive++;
Marko Mikulicic 0:c0ecb8bf28eb 20507 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20508
Marko Mikulicic 0:c0ecb8bf28eb 20509 /*
Marko Mikulicic 0:c0ecb8bf28eb 20510 * TODO(mkm): minor opt possible since most of the fields
Marko Mikulicic 0:c0ecb8bf28eb 20511 * are overwritten downstream, but not worth the yak shave time
Marko Mikulicic 0:c0ecb8bf28eb 20512 * when fields are added to GC-able structures */
Marko Mikulicic 0:c0ecb8bf28eb 20513 memset(r, 0, a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 20514 return (void *) r;
Marko Mikulicic 0:c0ecb8bf28eb 20515 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20516 }
Marko Mikulicic 0:c0ecb8bf28eb 20517
Marko Mikulicic 0:c0ecb8bf28eb 20518 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 20519 /*
Marko Mikulicic 0:c0ecb8bf28eb 20520 * Scans trough the memory blocks registered in the malloc trace.
Marko Mikulicic 0:c0ecb8bf28eb 20521 * Free the unmarked ones and reset the mark on the rest.
Marko Mikulicic 0:c0ecb8bf28eb 20522 */
Marko Mikulicic 0:c0ecb8bf28eb 20523 void gc_sweep_malloc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20524 struct gc_cell **cur;
Marko Mikulicic 0:c0ecb8bf28eb 20525 for (cur = (struct gc_cell **) v7->malloc_trace.buf;
Marko Mikulicic 0:c0ecb8bf28eb 20526 cur < (struct gc_cell **) (v7->malloc_trace.buf + v7->malloc_trace.len);
Marko Mikulicic 0:c0ecb8bf28eb 20527 cur++) {
Marko Mikulicic 0:c0ecb8bf28eb 20528 if (*cur == NULL) continue;
Marko Mikulicic 0:c0ecb8bf28eb 20529
Marko Mikulicic 0:c0ecb8bf28eb 20530 if (MARKED(*cur)) {
Marko Mikulicic 0:c0ecb8bf28eb 20531 UNMARK(*cur);
Marko Mikulicic 0:c0ecb8bf28eb 20532 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20533 free(*cur);
Marko Mikulicic 0:c0ecb8bf28eb 20534 /* TODO(mkm): compact malloc trace buffer */
Marko Mikulicic 0:c0ecb8bf28eb 20535 *cur = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20536 }
Marko Mikulicic 0:c0ecb8bf28eb 20537 }
Marko Mikulicic 0:c0ecb8bf28eb 20538 }
Marko Mikulicic 0:c0ecb8bf28eb 20539 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20540
Marko Mikulicic 0:c0ecb8bf28eb 20541 /*
Marko Mikulicic 0:c0ecb8bf28eb 20542 * Scans the arena and add all unmarked cells to the free list.
Marko Mikulicic 0:c0ecb8bf28eb 20543 *
Marko Mikulicic 0:c0ecb8bf28eb 20544 * Empty blocks get deallocated. The head of the free list will contais cells
Marko Mikulicic 0:c0ecb8bf28eb 20545 * from the last (oldest) block. Cells will thus be allocated in block order.
Marko Mikulicic 0:c0ecb8bf28eb 20546 */
Marko Mikulicic 0:c0ecb8bf28eb 20547 void gc_sweep(struct v7 *v7, struct gc_arena *a, size_t start) {
Marko Mikulicic 0:c0ecb8bf28eb 20548 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20549 struct gc_cell *cur;
Marko Mikulicic 0:c0ecb8bf28eb 20550 struct gc_block **prevp = &a->blocks;
Marko Mikulicic 0:c0ecb8bf28eb 20551 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20552 a->alive = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20553 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20554
Marko Mikulicic 0:c0ecb8bf28eb 20555 /*
Marko Mikulicic 0:c0ecb8bf28eb 20556 * Before we sweep, we should mark all free cells in a way that is
Marko Mikulicic 0:c0ecb8bf28eb 20557 * distinguishable from marked used cells.
Marko Mikulicic 0:c0ecb8bf28eb 20558 */
Marko Mikulicic 0:c0ecb8bf28eb 20559 {
Marko Mikulicic 0:c0ecb8bf28eb 20560 struct gc_cell *next;
Marko Mikulicic 0:c0ecb8bf28eb 20561 for (cur = a->free; cur != NULL; cur = next) {
Marko Mikulicic 0:c0ecb8bf28eb 20562 next = cur->head.link;
Marko Mikulicic 0:c0ecb8bf28eb 20563 MARK_FREE(cur);
Marko Mikulicic 0:c0ecb8bf28eb 20564 }
Marko Mikulicic 0:c0ecb8bf28eb 20565 }
Marko Mikulicic 0:c0ecb8bf28eb 20566
Marko Mikulicic 0:c0ecb8bf28eb 20567 /*
Marko Mikulicic 0:c0ecb8bf28eb 20568 * We'll rebuild the whole `free` list, so initially we just reset it
Marko Mikulicic 0:c0ecb8bf28eb 20569 */
Marko Mikulicic 0:c0ecb8bf28eb 20570 a->free = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20571
Marko Mikulicic 0:c0ecb8bf28eb 20572 for (b = a->blocks; b != NULL;) {
Marko Mikulicic 0:c0ecb8bf28eb 20573 size_t freed_in_block = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20574 /*
Marko Mikulicic 0:c0ecb8bf28eb 20575 * if it turns out that this block is 100% garbage
Marko Mikulicic 0:c0ecb8bf28eb 20576 * we can release the whole block, but the addition
Marko Mikulicic 0:c0ecb8bf28eb 20577 * of it's cells to the free list has to be undone.
Marko Mikulicic 0:c0ecb8bf28eb 20578 */
Marko Mikulicic 0:c0ecb8bf28eb 20579 struct gc_cell *prev_free = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20580
Marko Mikulicic 0:c0ecb8bf28eb 20581 for (cur = GC_CELL_OP(a, b->base, +, start);
Marko Mikulicic 0:c0ecb8bf28eb 20582 cur < GC_CELL_OP(a, b->base, +, b->size);
Marko Mikulicic 0:c0ecb8bf28eb 20583 cur = GC_CELL_OP(a, cur, +, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 20584 if (MARKED(cur)) {
Marko Mikulicic 0:c0ecb8bf28eb 20585 /* The cell is used and marked */
Marko Mikulicic 0:c0ecb8bf28eb 20586 UNMARK(cur);
Marko Mikulicic 0:c0ecb8bf28eb 20587 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20588 a->alive++;
Marko Mikulicic 0:c0ecb8bf28eb 20589 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20590 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20591 /*
Marko Mikulicic 0:c0ecb8bf28eb 20592 * The cell is either:
Marko Mikulicic 0:c0ecb8bf28eb 20593 * - free
Marko Mikulicic 0:c0ecb8bf28eb 20594 * - garbage that's about to be freed
Marko Mikulicic 0:c0ecb8bf28eb 20595 */
Marko Mikulicic 0:c0ecb8bf28eb 20596
Marko Mikulicic 0:c0ecb8bf28eb 20597 if (MARKED_FREE(cur)) {
Marko Mikulicic 0:c0ecb8bf28eb 20598 /* The cell is free, so, just unmark it */
Marko Mikulicic 0:c0ecb8bf28eb 20599 UNMARK_FREE(cur);
Marko Mikulicic 0:c0ecb8bf28eb 20600 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20601 /*
Marko Mikulicic 0:c0ecb8bf28eb 20602 * The cell is used and should be freed: call the destructor and
Marko Mikulicic 0:c0ecb8bf28eb 20603 * reset the memory
Marko Mikulicic 0:c0ecb8bf28eb 20604 */
Marko Mikulicic 0:c0ecb8bf28eb 20605 if (a->destructor != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20606 a->destructor(v7, cur);
Marko Mikulicic 0:c0ecb8bf28eb 20607 }
Marko Mikulicic 0:c0ecb8bf28eb 20608 memset(cur, 0, a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 20609 }
Marko Mikulicic 0:c0ecb8bf28eb 20610
Marko Mikulicic 0:c0ecb8bf28eb 20611 /* Add this cell to the `free` list */
Marko Mikulicic 0:c0ecb8bf28eb 20612 cur->head.link = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20613 a->free = cur;
Marko Mikulicic 0:c0ecb8bf28eb 20614 freed_in_block++;
Marko Mikulicic 0:c0ecb8bf28eb 20615 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20616 a->garbage++;
Marko Mikulicic 0:c0ecb8bf28eb 20617 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20618 }
Marko Mikulicic 0:c0ecb8bf28eb 20619 }
Marko Mikulicic 0:c0ecb8bf28eb 20620
Marko Mikulicic 0:c0ecb8bf28eb 20621 /*
Marko Mikulicic 0:c0ecb8bf28eb 20622 * don't free the initial block, which is at the tail
Marko Mikulicic 0:c0ecb8bf28eb 20623 * because it has a special size aimed at reducing waste
Marko Mikulicic 0:c0ecb8bf28eb 20624 * and simplifying initial startup. TODO(mkm): improve
Marko Mikulicic 0:c0ecb8bf28eb 20625 * */
Marko Mikulicic 0:c0ecb8bf28eb 20626 if (b->next != NULL && freed_in_block == b->size) {
Marko Mikulicic 0:c0ecb8bf28eb 20627 *prevp = b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20628 gc_free_block(b);
Marko Mikulicic 0:c0ecb8bf28eb 20629 b = *prevp;
Marko Mikulicic 0:c0ecb8bf28eb 20630 a->free = prev_free;
Marko Mikulicic 0:c0ecb8bf28eb 20631 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20632 prevp = &b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20633 b = b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20634 }
Marko Mikulicic 0:c0ecb8bf28eb 20635 }
Marko Mikulicic 0:c0ecb8bf28eb 20636 }
Marko Mikulicic 0:c0ecb8bf28eb 20637
Marko Mikulicic 0:c0ecb8bf28eb 20638 /*
Marko Mikulicic 0:c0ecb8bf28eb 20639 * dense arrays contain only one property pointing to an mbuf with array values.
Marko Mikulicic 0:c0ecb8bf28eb 20640 */
Marko Mikulicic 0:c0ecb8bf28eb 20641 V7_PRIVATE void gc_mark_dense_array(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 20642 struct v7_generic_object *obj) {
Marko Mikulicic 0:c0ecb8bf28eb 20643 val_t v;
Marko Mikulicic 0:c0ecb8bf28eb 20644 struct mbuf *mbuf;
Marko Mikulicic 0:c0ecb8bf28eb 20645 val_t *vp;
Marko Mikulicic 0:c0ecb8bf28eb 20646
Marko Mikulicic 0:c0ecb8bf28eb 20647 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 20648 /* TODO(mkm): use this when dense array promotion is implemented */
Marko Mikulicic 0:c0ecb8bf28eb 20649 v = obj->properties->value;
Marko Mikulicic 0:c0ecb8bf28eb 20650 #else
Marko Mikulicic 0:c0ecb8bf28eb 20651 v = v7_get(v7, v7_object_to_value(&obj->base), "", 0);
Marko Mikulicic 0:c0ecb8bf28eb 20652 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20653
Marko Mikulicic 0:c0ecb8bf28eb 20654 mbuf = (struct mbuf *) v7_get_ptr(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 20655
Marko Mikulicic 0:c0ecb8bf28eb 20656 /* function scope pointer is aliased to the object's prototype pointer */
Marko Mikulicic 0:c0ecb8bf28eb 20657 gc_mark(v7, v7_object_to_value(obj_prototype(v7, &obj->base)));
Marko Mikulicic 0:c0ecb8bf28eb 20658 MARK(obj);
Marko Mikulicic 0:c0ecb8bf28eb 20659
Marko Mikulicic 0:c0ecb8bf28eb 20660 if (mbuf == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 20661 for (vp = (val_t *) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 20662 gc_mark(v7, *vp);
Marko Mikulicic 0:c0ecb8bf28eb 20663 gc_mark_string(v7, vp);
Marko Mikulicic 0:c0ecb8bf28eb 20664 }
Marko Mikulicic 0:c0ecb8bf28eb 20665 UNMARK(obj);
Marko Mikulicic 0:c0ecb8bf28eb 20666 }
Marko Mikulicic 0:c0ecb8bf28eb 20667
Marko Mikulicic 0:c0ecb8bf28eb 20668 V7_PRIVATE void gc_mark(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20669 struct v7_object *obj_base;
Marko Mikulicic 0:c0ecb8bf28eb 20670 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 20671 struct v7_property *next;
Marko Mikulicic 0:c0ecb8bf28eb 20672
Marko Mikulicic 0:c0ecb8bf28eb 20673 if (!v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20674 return;
Marko Mikulicic 0:c0ecb8bf28eb 20675 }
Marko Mikulicic 0:c0ecb8bf28eb 20676 obj_base = get_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 20677
Marko Mikulicic 0:c0ecb8bf28eb 20678 /*
Marko Mikulicic 0:c0ecb8bf28eb 20679 * we ignore objects that are not managed by V7 heap, such as frozen
Marko Mikulicic 0:c0ecb8bf28eb 20680 * objects, especially when on flash.
Marko Mikulicic 0:c0ecb8bf28eb 20681 */
Marko Mikulicic 0:c0ecb8bf28eb 20682 if (obj_base->attributes & V7_OBJ_OFF_HEAP) {
Marko Mikulicic 0:c0ecb8bf28eb 20683 return;
Marko Mikulicic 0:c0ecb8bf28eb 20684 }
Marko Mikulicic 0:c0ecb8bf28eb 20685
Marko Mikulicic 0:c0ecb8bf28eb 20686 /*
Marko Mikulicic 0:c0ecb8bf28eb 20687 * we treat all object like things like objects but they might be functions,
Marko Mikulicic 0:c0ecb8bf28eb 20688 * gc_gheck_val checks the appropriate arena per actual value type.
Marko Mikulicic 0:c0ecb8bf28eb 20689 */
Marko Mikulicic 0:c0ecb8bf28eb 20690 if (!gc_check_val(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20691 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20692 }
Marko Mikulicic 0:c0ecb8bf28eb 20693
Marko Mikulicic 0:c0ecb8bf28eb 20694 if (MARKED(obj_base)) return;
Marko Mikulicic 0:c0ecb8bf28eb 20695
Marko Mikulicic 0:c0ecb8bf28eb 20696 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 20697 if (v7->freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20698 freeze_obj(v7, v7->freeze_file, v);
Marko Mikulicic 0:c0ecb8bf28eb 20699 }
Marko Mikulicic 0:c0ecb8bf28eb 20700 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20701
Marko Mikulicic 0:c0ecb8bf28eb 20702 if (obj_base->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 20703 struct v7_generic_object *obj = get_generic_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 20704 gc_mark_dense_array(v7, obj);
Marko Mikulicic 0:c0ecb8bf28eb 20705 }
Marko Mikulicic 0:c0ecb8bf28eb 20706
Marko Mikulicic 0:c0ecb8bf28eb 20707 /* mark object itself, and its properties */
Marko Mikulicic 0:c0ecb8bf28eb 20708 for ((prop = obj_base->properties), MARK(obj_base); prop != NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20709 prop = next) {
Marko Mikulicic 0:c0ecb8bf28eb 20710 if (prop->attributes & _V7_PROPERTY_OFF_HEAP) {
Marko Mikulicic 0:c0ecb8bf28eb 20711 break;
Marko Mikulicic 0:c0ecb8bf28eb 20712 }
Marko Mikulicic 0:c0ecb8bf28eb 20713
Marko Mikulicic 0:c0ecb8bf28eb 20714 if (!gc_check_ptr(&v7->property_arena, prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 20715 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20716 }
Marko Mikulicic 0:c0ecb8bf28eb 20717
Marko Mikulicic 0:c0ecb8bf28eb 20718 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 20719 if (v7->freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20720 freeze_prop(v7, v7->freeze_file, prop);
Marko Mikulicic 0:c0ecb8bf28eb 20721 }
Marko Mikulicic 0:c0ecb8bf28eb 20722 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20723
Marko Mikulicic 0:c0ecb8bf28eb 20724 gc_mark_string(v7, &prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 20725 gc_mark_string(v7, &prop->name);
Marko Mikulicic 0:c0ecb8bf28eb 20726 gc_mark(v7, prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 20727
Marko Mikulicic 0:c0ecb8bf28eb 20728 next = prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 20729 MARK(prop);
Marko Mikulicic 0:c0ecb8bf28eb 20730 }
Marko Mikulicic 0:c0ecb8bf28eb 20731
Marko Mikulicic 0:c0ecb8bf28eb 20732 /* mark object's prototype */
Marko Mikulicic 0:c0ecb8bf28eb 20733 gc_mark(v7, v7_get_proto(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 20734
Marko Mikulicic 0:c0ecb8bf28eb 20735 if (is_js_function(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20736 struct v7_js_function *func = get_js_function_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 20737
Marko Mikulicic 0:c0ecb8bf28eb 20738 /* mark function's scope */
Marko Mikulicic 0:c0ecb8bf28eb 20739 gc_mark(v7, v7_object_to_value(&func->scope->base));
Marko Mikulicic 0:c0ecb8bf28eb 20740
Marko Mikulicic 0:c0ecb8bf28eb 20741 if (func->bcode != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20742 gc_mark_vec_val(v7, &func->bcode->lit);
Marko Mikulicic 0:c0ecb8bf28eb 20743 }
Marko Mikulicic 0:c0ecb8bf28eb 20744 }
Marko Mikulicic 0:c0ecb8bf28eb 20745 }
Marko Mikulicic 0:c0ecb8bf28eb 20746
Marko Mikulicic 0:c0ecb8bf28eb 20747 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20748
Marko Mikulicic 0:c0ecb8bf28eb 20749 V7_PRIVATE size_t gc_arena_size(struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20750 size_t size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20751 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20752 for (b = a->blocks; b != NULL; b = b->next) {
Marko Mikulicic 0:c0ecb8bf28eb 20753 size += b->size;
Marko Mikulicic 0:c0ecb8bf28eb 20754 }
Marko Mikulicic 0:c0ecb8bf28eb 20755 return size;
Marko Mikulicic 0:c0ecb8bf28eb 20756 }
Marko Mikulicic 0:c0ecb8bf28eb 20757
Marko Mikulicic 0:c0ecb8bf28eb 20758 /*
Marko Mikulicic 0:c0ecb8bf28eb 20759 * TODO(dfrank): move to core
Marko Mikulicic 0:c0ecb8bf28eb 20760 */
Marko Mikulicic 0:c0ecb8bf28eb 20761 int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what) {
Marko Mikulicic 0:c0ecb8bf28eb 20762 switch (what) {
Marko Mikulicic 0:c0ecb8bf28eb 20763 case V7_HEAP_STAT_HEAP_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20764 return gc_arena_size(&v7->generic_object_arena) *
Marko Mikulicic 0:c0ecb8bf28eb 20765 v7->generic_object_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20766 gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20767 gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20768 case V7_HEAP_STAT_HEAP_USED:
Marko Mikulicic 0:c0ecb8bf28eb 20769 return v7->generic_object_arena.alive *
Marko Mikulicic 0:c0ecb8bf28eb 20770 v7->generic_object_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20771 v7->function_arena.alive * v7->function_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20772 v7->property_arena.alive * v7->property_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20773 case V7_HEAP_STAT_STRING_HEAP_RESERVED:
Marko Mikulicic 0:c0ecb8bf28eb 20774 return v7->owned_strings.size;
Marko Mikulicic 0:c0ecb8bf28eb 20775 case V7_HEAP_STAT_STRING_HEAP_USED:
Marko Mikulicic 0:c0ecb8bf28eb 20776 return v7->owned_strings.len;
Marko Mikulicic 0:c0ecb8bf28eb 20777 case V7_HEAP_STAT_OBJ_HEAP_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20778 return gc_arena_size(&v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20779 case V7_HEAP_STAT_OBJ_HEAP_FREE:
Marko Mikulicic 0:c0ecb8bf28eb 20780 return gc_arena_size(&v7->generic_object_arena) -
Marko Mikulicic 0:c0ecb8bf28eb 20781 v7->generic_object_arena.alive;
Marko Mikulicic 0:c0ecb8bf28eb 20782 case V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20783 return v7->generic_object_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20784 case V7_HEAP_STAT_FUNC_HEAP_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20785 return gc_arena_size(&v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20786 case V7_HEAP_STAT_FUNC_HEAP_FREE:
Marko Mikulicic 0:c0ecb8bf28eb 20787 return gc_arena_size(&v7->function_arena) - v7->function_arena.alive;
Marko Mikulicic 0:c0ecb8bf28eb 20788 case V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20789 return v7->function_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20790 case V7_HEAP_STAT_PROP_HEAP_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20791 return gc_arena_size(&v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20792 case V7_HEAP_STAT_PROP_HEAP_FREE:
Marko Mikulicic 0:c0ecb8bf28eb 20793 return gc_arena_size(&v7->property_arena) - v7->property_arena.alive;
Marko Mikulicic 0:c0ecb8bf28eb 20794 case V7_HEAP_STAT_PROP_HEAP_CELL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20795 return v7->property_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20796 case V7_HEAP_STAT_FUNC_AST_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20797 return v7->function_arena_ast_size;
Marko Mikulicic 0:c0ecb8bf28eb 20798 case V7_HEAP_STAT_BCODE_OPS_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20799 return v7->bcode_ops_size;
Marko Mikulicic 0:c0ecb8bf28eb 20800 case V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20801 return v7->bcode_lit_total_size;
Marko Mikulicic 0:c0ecb8bf28eb 20802 case V7_HEAP_STAT_BCODE_LIT_DESER_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20803 return v7->bcode_lit_deser_size;
Marko Mikulicic 0:c0ecb8bf28eb 20804 case V7_HEAP_STAT_FUNC_OWNED:
Marko Mikulicic 0:c0ecb8bf28eb 20805 return v7->owned_values.len / sizeof(val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 20806 case V7_HEAP_STAT_FUNC_OWNED_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20807 return v7->owned_values.size / sizeof(val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 20808 }
Marko Mikulicic 0:c0ecb8bf28eb 20809
Marko Mikulicic 0:c0ecb8bf28eb 20810 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 20811 }
Marko Mikulicic 0:c0ecb8bf28eb 20812 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20813
Marko Mikulicic 0:c0ecb8bf28eb 20814 V7_PRIVATE void gc_dump_arena_stats(const char *msg, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20815 (void) msg;
Marko Mikulicic 0:c0ecb8bf28eb 20816 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 20817 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 20818 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20819 if (a->verbose) {
Marko Mikulicic 0:c0ecb8bf28eb 20820 fprintf(stderr, "%s: total allocations %lu, max %lu, alive %lu\n", msg,
Marko Mikulicic 0:c0ecb8bf28eb 20821 (long unsigned int) a->allocations,
Marko Mikulicic 0:c0ecb8bf28eb 20822 (long unsigned int) gc_arena_size(a), (long unsigned int) a->alive);
Marko Mikulicic 0:c0ecb8bf28eb 20823 }
Marko Mikulicic 0:c0ecb8bf28eb 20824 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20825 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20826 }
Marko Mikulicic 0:c0ecb8bf28eb 20827
Marko Mikulicic 0:c0ecb8bf28eb 20828 V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20829 return (((uint64_t)(uintptr_t) get_ptr(v)) & ~V7_TAG_MASK)
Marko Mikulicic 0:c0ecb8bf28eb 20830 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20831 & 0xFFFFFFFF
Marko Mikulicic 0:c0ecb8bf28eb 20832 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20833 ;
Marko Mikulicic 0:c0ecb8bf28eb 20834 }
Marko Mikulicic 0:c0ecb8bf28eb 20835
Marko Mikulicic 0:c0ecb8bf28eb 20836 V7_PRIVATE val_t gc_string_val_from_offset(uint64_t s) {
Marko Mikulicic 0:c0ecb8bf28eb 20837 return s | V7_TAG_STRING_O;
Marko Mikulicic 0:c0ecb8bf28eb 20838 }
Marko Mikulicic 0:c0ecb8bf28eb 20839
Marko Mikulicic 0:c0ecb8bf28eb 20840 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20841
Marko Mikulicic 0:c0ecb8bf28eb 20842 static uint16_t next_asn(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20843 if (v7->gc_next_asn == 0xFFFF) {
Marko Mikulicic 0:c0ecb8bf28eb 20844 /* Wrap around explicitly. */
Marko Mikulicic 0:c0ecb8bf28eb 20845 v7->gc_next_asn = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20846 return 0xFFFF;
Marko Mikulicic 0:c0ecb8bf28eb 20847 }
Marko Mikulicic 0:c0ecb8bf28eb 20848 return v7->gc_next_asn++;
Marko Mikulicic 0:c0ecb8bf28eb 20849 }
Marko Mikulicic 0:c0ecb8bf28eb 20850
Marko Mikulicic 0:c0ecb8bf28eb 20851 uint16_t gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 20852 uint16_t asn = next_asn(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20853 (void) str;
Marko Mikulicic 0:c0ecb8bf28eb 20854 (void) len;
Marko Mikulicic 0:c0ecb8bf28eb 20855 #ifdef V7_GC_VERBOSE
Marko Mikulicic 0:c0ecb8bf28eb 20856 /*
Marko Mikulicic 0:c0ecb8bf28eb 20857 * ESP SDK printf cannot cope with null strings
Marko Mikulicic 0:c0ecb8bf28eb 20858 * as created by s_concat.
Marko Mikulicic 0:c0ecb8bf28eb 20859 */
Marko Mikulicic 0:c0ecb8bf28eb 20860 if (str == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20861 fprintf(stderr, "GC ASN %d: <nil>\n", asn);
Marko Mikulicic 0:c0ecb8bf28eb 20862 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20863 fprintf(stderr, "GC ASN %d: \"%.*s\"\n", asn, (int) len, str);
Marko Mikulicic 0:c0ecb8bf28eb 20864 }
Marko Mikulicic 0:c0ecb8bf28eb 20865 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20866 #ifdef V7_GC_PANIC_ON_ASN
Marko Mikulicic 0:c0ecb8bf28eb 20867 if (asn == (V7_GC_PANIC_ON_ASN)) {
Marko Mikulicic 0:c0ecb8bf28eb 20868 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20869 }
Marko Mikulicic 0:c0ecb8bf28eb 20870 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20871 return asn;
Marko Mikulicic 0:c0ecb8bf28eb 20872 }
Marko Mikulicic 0:c0ecb8bf28eb 20873
Marko Mikulicic 0:c0ecb8bf28eb 20874 int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 20875 /*
Marko Mikulicic 0:c0ecb8bf28eb 20876 * This functions attempts to handle integer wraparound in a naive way and
Marko Mikulicic 0:c0ecb8bf28eb 20877 * will give false positives when more than 65536 strings are allocated
Marko Mikulicic 0:c0ecb8bf28eb 20878 * between GC runs.
Marko Mikulicic 0:c0ecb8bf28eb 20879 */
Marko Mikulicic 0:c0ecb8bf28eb 20880 int r = (n >= v7->gc_min_asn && n < v7->gc_next_asn) ||
Marko Mikulicic 0:c0ecb8bf28eb 20881 (v7->gc_min_asn > v7->gc_next_asn &&
Marko Mikulicic 0:c0ecb8bf28eb 20882 (n >= v7->gc_min_asn || n < v7->gc_next_asn));
Marko Mikulicic 0:c0ecb8bf28eb 20883 if (!r) {
Marko Mikulicic 0:c0ecb8bf28eb 20884 fprintf(stderr, "GC ASN %d is not in [%d,%d)\n", n, v7->gc_min_asn,
Marko Mikulicic 0:c0ecb8bf28eb 20885 v7->gc_next_asn);
Marko Mikulicic 0:c0ecb8bf28eb 20886 }
Marko Mikulicic 0:c0ecb8bf28eb 20887 return r;
Marko Mikulicic 0:c0ecb8bf28eb 20888 }
Marko Mikulicic 0:c0ecb8bf28eb 20889
Marko Mikulicic 0:c0ecb8bf28eb 20890 void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 20891 if (!gc_is_valid_allocation_seqn(v7, n)) {
Marko Mikulicic 0:c0ecb8bf28eb 20892 /*
Marko Mikulicic 0:c0ecb8bf28eb 20893 * TODO(dfrank) throw exception if V7_GC_ASN_PANIC is not defined.
Marko Mikulicic 0:c0ecb8bf28eb 20894 */
Marko Mikulicic 0:c0ecb8bf28eb 20895 #if 0 && !defined(V7_GC_ASN_PANIC)
Marko Mikulicic 0:c0ecb8bf28eb 20896 throw_exception(v7, INTERNAL_ERROR, "Invalid ASN: %d", (int) n);
Marko Mikulicic 0:c0ecb8bf28eb 20897 #else
Marko Mikulicic 0:c0ecb8bf28eb 20898 fprintf(stderr, "Invalid ASN: %d\n", (int) n);
Marko Mikulicic 0:c0ecb8bf28eb 20899 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20900 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20901 }
Marko Mikulicic 0:c0ecb8bf28eb 20902 }
Marko Mikulicic 0:c0ecb8bf28eb 20903
Marko Mikulicic 0:c0ecb8bf28eb 20904 #endif /* V7_DISABLE_STR_ALLOC_SEQ */
Marko Mikulicic 0:c0ecb8bf28eb 20905
Marko Mikulicic 0:c0ecb8bf28eb 20906 /* Mark a string value */
Marko Mikulicic 0:c0ecb8bf28eb 20907 void gc_mark_string(struct v7 *v7, val_t *v) {
Marko Mikulicic 0:c0ecb8bf28eb 20908 val_t h, tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20909 char *s;
Marko Mikulicic 0:c0ecb8bf28eb 20910
Marko Mikulicic 0:c0ecb8bf28eb 20911 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 20912
Marko Mikulicic 0:c0ecb8bf28eb 20913 /*
Marko Mikulicic 0:c0ecb8bf28eb 20914 * If a value points to an unmarked string we shall:
Marko Mikulicic 0:c0ecb8bf28eb 20915 * 1. save the first 6 bytes of the string
Marko Mikulicic 0:c0ecb8bf28eb 20916 * since we need to be able to distinguish real values from
Marko Mikulicic 0:c0ecb8bf28eb 20917 * the saved first 6 bytes of the string, we need to tag the chunk
Marko Mikulicic 0:c0ecb8bf28eb 20918 * as V7_TAG_STRING_C
Marko Mikulicic 0:c0ecb8bf28eb 20919 * 2. encode value's address (v) into the first 6 bytes of the string.
Marko Mikulicic 0:c0ecb8bf28eb 20920 * 3. put the saved 8 bytes (tag + chunk) back into the value.
Marko Mikulicic 0:c0ecb8bf28eb 20921 * 4. mark the string by putting '\1' in the NUL terminator of the previous
Marko Mikulicic 0:c0ecb8bf28eb 20922 * string chunk.
Marko Mikulicic 0:c0ecb8bf28eb 20923 *
Marko Mikulicic 0:c0ecb8bf28eb 20924 * If a value points to an already marked string we shall:
Marko Mikulicic 0:c0ecb8bf28eb 20925 * (0, <6 bytes of a pointer to a val_t>), hence we have to skip
Marko Mikulicic 0:c0ecb8bf28eb 20926 * the first byte. We tag the value pointer as a V7_TAG_FOREIGN
Marko Mikulicic 0:c0ecb8bf28eb 20927 * so that it won't be followed during recursive mark.
Marko Mikulicic 0:c0ecb8bf28eb 20928 *
Marko Mikulicic 0:c0ecb8bf28eb 20929 * ... the rest is the same
Marko Mikulicic 0:c0ecb8bf28eb 20930 *
Marko Mikulicic 0:c0ecb8bf28eb 20931 * Note: 64-bit pointers can be represented with 48-bits
Marko Mikulicic 0:c0ecb8bf28eb 20932 */
Marko Mikulicic 0:c0ecb8bf28eb 20933
Marko Mikulicic 0:c0ecb8bf28eb 20934 /* clang-format on */
Marko Mikulicic 0:c0ecb8bf28eb 20935
Marko Mikulicic 0:c0ecb8bf28eb 20936 if ((*v & V7_TAG_MASK) != V7_TAG_STRING_O) {
Marko Mikulicic 0:c0ecb8bf28eb 20937 return;
Marko Mikulicic 0:c0ecb8bf28eb 20938 }
Marko Mikulicic 0:c0ecb8bf28eb 20939
Marko Mikulicic 0:c0ecb8bf28eb 20940 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 20941 if (v7->freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20942 return;
Marko Mikulicic 0:c0ecb8bf28eb 20943 }
Marko Mikulicic 0:c0ecb8bf28eb 20944 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20945
Marko Mikulicic 0:c0ecb8bf28eb 20946 #ifdef V7_GC_VERBOSE
Marko Mikulicic 0:c0ecb8bf28eb 20947 {
Marko Mikulicic 0:c0ecb8bf28eb 20948 uint16_t asn = (*v >> 32) & 0xFFFF;
Marko Mikulicic 0:c0ecb8bf28eb 20949 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 20950 fprintf(stderr, "GC marking ASN %d: '%s'\n", asn,
Marko Mikulicic 0:c0ecb8bf28eb 20951 v7_get_string(v7, v, &size));
Marko Mikulicic 0:c0ecb8bf28eb 20952 }
Marko Mikulicic 0:c0ecb8bf28eb 20953 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20954
Marko Mikulicic 0:c0ecb8bf28eb 20955 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20956 gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 20957 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20958
Marko Mikulicic 0:c0ecb8bf28eb 20959 s = v7->owned_strings.buf + gc_string_val_to_offset(*v);
Marko Mikulicic 0:c0ecb8bf28eb 20960 assert(s < v7->owned_strings.buf + v7->owned_strings.len);
Marko Mikulicic 0:c0ecb8bf28eb 20961 if (s[-1] == '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 20962 memcpy(&tmp, s, sizeof(tmp) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20963 tmp |= V7_TAG_STRING_C;
Marko Mikulicic 0:c0ecb8bf28eb 20964 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20965 memcpy(&tmp, s, sizeof(tmp) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20966 tmp |= V7_TAG_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 20967 }
Marko Mikulicic 0:c0ecb8bf28eb 20968
Marko Mikulicic 0:c0ecb8bf28eb 20969 h = (val_t)(uintptr_t) v;
Marko Mikulicic 0:c0ecb8bf28eb 20970 s[-1] = 1;
Marko Mikulicic 0:c0ecb8bf28eb 20971 memcpy(s, &h, sizeof(h) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20972 memcpy(v, &tmp, sizeof(tmp));
Marko Mikulicic 0:c0ecb8bf28eb 20973 }
Marko Mikulicic 0:c0ecb8bf28eb 20974
Marko Mikulicic 0:c0ecb8bf28eb 20975 void gc_compact_strings(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20976 char *p = v7->owned_strings.buf + 1;
Marko Mikulicic 0:c0ecb8bf28eb 20977 uint64_t h, next, head = 1;
Marko Mikulicic 0:c0ecb8bf28eb 20978 int len, llen;
Marko Mikulicic 0:c0ecb8bf28eb 20979
Marko Mikulicic 0:c0ecb8bf28eb 20980 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20981 v7->gc_min_asn = v7->gc_next_asn;
Marko Mikulicic 0:c0ecb8bf28eb 20982 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20983 while (p < v7->owned_strings.buf + v7->owned_strings.len) {
Marko Mikulicic 0:c0ecb8bf28eb 20984 if (p[-1] == '\1') {
Marko Mikulicic 0:c0ecb8bf28eb 20985 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20986 /* Not using gc_next_allocation_seqn() as we don't have full string. */
Marko Mikulicic 0:c0ecb8bf28eb 20987 uint16_t asn = next_asn(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20988 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20989 /* relocate and update ptrs */
Marko Mikulicic 0:c0ecb8bf28eb 20990 h = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20991 memcpy(&h, p, sizeof(h) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20992
Marko Mikulicic 0:c0ecb8bf28eb 20993 /*
Marko Mikulicic 0:c0ecb8bf28eb 20994 * relocate pointers until we find the tail.
Marko Mikulicic 0:c0ecb8bf28eb 20995 * The tail is marked with V7_TAG_STRING_C,
Marko Mikulicic 0:c0ecb8bf28eb 20996 * while val_t link pointers are tagged with V7_TAG_FOREIGN
Marko Mikulicic 0:c0ecb8bf28eb 20997 */
Marko Mikulicic 0:c0ecb8bf28eb 20998 for (; (h & V7_TAG_MASK) != V7_TAG_STRING_C; h = next) {
Marko Mikulicic 0:c0ecb8bf28eb 20999 h &= ~V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 21000 memcpy(&next, (char *) (uintptr_t) h, sizeof(h));
Marko Mikulicic 0:c0ecb8bf28eb 21001
Marko Mikulicic 0:c0ecb8bf28eb 21002 *(val_t *) (uintptr_t) h = gc_string_val_from_offset(head)
Marko Mikulicic 0:c0ecb8bf28eb 21003 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 21004 | ((val_t) asn << 32)
Marko Mikulicic 0:c0ecb8bf28eb 21005 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21006 ;
Marko Mikulicic 0:c0ecb8bf28eb 21007 }
Marko Mikulicic 0:c0ecb8bf28eb 21008 h &= ~V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 21009
Marko Mikulicic 0:c0ecb8bf28eb 21010 /*
Marko Mikulicic 0:c0ecb8bf28eb 21011 * the tail contains the first 6 bytes we stole from
Marko Mikulicic 0:c0ecb8bf28eb 21012 * the actual string.
Marko Mikulicic 0:c0ecb8bf28eb 21013 */
Marko Mikulicic 0:c0ecb8bf28eb 21014 len = decode_varint((unsigned char *) &h, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 21015 len += llen + 1;
Marko Mikulicic 0:c0ecb8bf28eb 21016
Marko Mikulicic 0:c0ecb8bf28eb 21017 /*
Marko Mikulicic 0:c0ecb8bf28eb 21018 * restore the saved 6 bytes
Marko Mikulicic 0:c0ecb8bf28eb 21019 * TODO(mkm): think about endianness
Marko Mikulicic 0:c0ecb8bf28eb 21020 */
Marko Mikulicic 0:c0ecb8bf28eb 21021 memcpy(p, &h, sizeof(h) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 21022
Marko Mikulicic 0:c0ecb8bf28eb 21023 /*
Marko Mikulicic 0:c0ecb8bf28eb 21024 * and relocate the string data by packing it to the left.
Marko Mikulicic 0:c0ecb8bf28eb 21025 */
Marko Mikulicic 0:c0ecb8bf28eb 21026 memmove(v7->owned_strings.buf + head, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 21027 v7->owned_strings.buf[head - 1] = 0x0;
Marko Mikulicic 0:c0ecb8bf28eb 21028 #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ)
Marko Mikulicic 0:c0ecb8bf28eb 21029 fprintf(stderr, "GC updated ASN %d: \"%.*s\"\n", asn, len - llen - 1,
Marko Mikulicic 0:c0ecb8bf28eb 21030 v7->owned_strings.buf + head + llen);
Marko Mikulicic 0:c0ecb8bf28eb 21031 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21032 p += len;
Marko Mikulicic 0:c0ecb8bf28eb 21033 head += len;
Marko Mikulicic 0:c0ecb8bf28eb 21034 } else {
Marko Mikulicic 0:c0ecb8bf28eb 21035 len = decode_varint((unsigned char *) p, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 21036 len += llen + 1;
Marko Mikulicic 0:c0ecb8bf28eb 21037
Marko Mikulicic 0:c0ecb8bf28eb 21038 p += len;
Marko Mikulicic 0:c0ecb8bf28eb 21039 }
Marko Mikulicic 0:c0ecb8bf28eb 21040 }
Marko Mikulicic 0:c0ecb8bf28eb 21041
Marko Mikulicic 0:c0ecb8bf28eb 21042 #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ)
Marko Mikulicic 0:c0ecb8bf28eb 21043 fprintf(stderr, "GC valid ASN range: [%d,%d)\n", v7->gc_min_asn,
Marko Mikulicic 0:c0ecb8bf28eb 21044 v7->gc_next_asn);
Marko Mikulicic 0:c0ecb8bf28eb 21045 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21046
Marko Mikulicic 0:c0ecb8bf28eb 21047 v7->owned_strings.len = head;
Marko Mikulicic 0:c0ecb8bf28eb 21048 }
Marko Mikulicic 0:c0ecb8bf28eb 21049
Marko Mikulicic 0:c0ecb8bf28eb 21050 void gc_dump_owned_strings(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 21051 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 21052 for (i = 0; i < v7->owned_strings.len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 21053 if (isprint((unsigned char) v7->owned_strings.buf[i])) {
Marko Mikulicic 0:c0ecb8bf28eb 21054 fputc(v7->owned_strings.buf[i], stderr);
Marko Mikulicic 0:c0ecb8bf28eb 21055 } else {
Marko Mikulicic 0:c0ecb8bf28eb 21056 fputc('.', stderr);
Marko Mikulicic 0:c0ecb8bf28eb 21057 }
Marko Mikulicic 0:c0ecb8bf28eb 21058 }
Marko Mikulicic 0:c0ecb8bf28eb 21059 fputc('\n', stderr);
Marko Mikulicic 0:c0ecb8bf28eb 21060 }
Marko Mikulicic 0:c0ecb8bf28eb 21061
Marko Mikulicic 0:c0ecb8bf28eb 21062 /*
Marko Mikulicic 0:c0ecb8bf28eb 21063 * builting on gcc, tried out by redefining it.
Marko Mikulicic 0:c0ecb8bf28eb 21064 * Using null pointer as base can trigger undefined behavior, hence
Marko Mikulicic 0:c0ecb8bf28eb 21065 * a portable workaround that involves a valid yet dummy pointer.
Marko Mikulicic 0:c0ecb8bf28eb 21066 * It's meant to be used as a contant expression.
Marko Mikulicic 0:c0ecb8bf28eb 21067 */
Marko Mikulicic 0:c0ecb8bf28eb 21068 #ifndef offsetof
Marko Mikulicic 0:c0ecb8bf28eb 21069 #define offsetof(st, m) (((ptrdiff_t)(&((st *) 32)->m)) - 32)
Marko Mikulicic 0:c0ecb8bf28eb 21070 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21071
Marko Mikulicic 0:c0ecb8bf28eb 21072 V7_PRIVATE void compute_need_gc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 21073 struct mbuf *m = &v7->owned_strings;
Marko Mikulicic 0:c0ecb8bf28eb 21074 if ((double) m->len / (double) m->size > 0.9) {
Marko Mikulicic 0:c0ecb8bf28eb 21075 v7->need_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 21076 }
Marko Mikulicic 0:c0ecb8bf28eb 21077 /* TODO(mkm): check free heap */
Marko Mikulicic 0:c0ecb8bf28eb 21078 }
Marko Mikulicic 0:c0ecb8bf28eb 21079
Marko Mikulicic 0:c0ecb8bf28eb 21080 V7_PRIVATE int maybe_gc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 21081 if (!v7->inhibit_gc) {
Marko Mikulicic 0:c0ecb8bf28eb 21082 v7_gc(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21083 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21084 }
Marko Mikulicic 0:c0ecb8bf28eb 21085 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 21086 }
Marko Mikulicic 0:c0ecb8bf28eb 21087 #if defined(V7_GC_VERBOSE)
Marko Mikulicic 0:c0ecb8bf28eb 21088 static int gc_pass = 0;
Marko Mikulicic 0:c0ecb8bf28eb 21089 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21090
Marko Mikulicic 0:c0ecb8bf28eb 21091 /*
Marko Mikulicic 0:c0ecb8bf28eb 21092 * mark an array of `val_t` values (*not pointers* to them)
Marko Mikulicic 0:c0ecb8bf28eb 21093 */
Marko Mikulicic 0:c0ecb8bf28eb 21094 static void gc_mark_val_array(struct v7 *v7, val_t *vals, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 21095 val_t *vp;
Marko Mikulicic 0:c0ecb8bf28eb 21096 for (vp = vals; vp < vals + len; vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 21097 gc_mark(v7, *vp);
Marko Mikulicic 0:c0ecb8bf28eb 21098 gc_mark_string(v7, vp);
Marko Mikulicic 0:c0ecb8bf28eb 21099 }
Marko Mikulicic 0:c0ecb8bf28eb 21100 }
Marko Mikulicic 0:c0ecb8bf28eb 21101
Marko Mikulicic 0:c0ecb8bf28eb 21102 /*
Marko Mikulicic 0:c0ecb8bf28eb 21103 * mark an mbuf containing *pointers* to `val_t` values
Marko Mikulicic 0:c0ecb8bf28eb 21104 */
Marko Mikulicic 0:c0ecb8bf28eb 21105 static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 21106 val_t **vp;
Marko Mikulicic 0:c0ecb8bf28eb 21107 for (vp = (val_t **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 21108 gc_mark(v7, **vp);
Marko Mikulicic 0:c0ecb8bf28eb 21109 gc_mark_string(v7, *vp);
Marko Mikulicic 0:c0ecb8bf28eb 21110 }
Marko Mikulicic 0:c0ecb8bf28eb 21111 }
Marko Mikulicic 0:c0ecb8bf28eb 21112
Marko Mikulicic 0:c0ecb8bf28eb 21113 /*
Marko Mikulicic 0:c0ecb8bf28eb 21114 * mark an mbuf containing `val_t` values (*not pointers* to them)
Marko Mikulicic 0:c0ecb8bf28eb 21115 */
Marko Mikulicic 0:c0ecb8bf28eb 21116 static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 21117 gc_mark_val_array(v7, (val_t *) mbuf->buf, mbuf->len / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21118 }
Marko Mikulicic 0:c0ecb8bf28eb 21119
Marko Mikulicic 0:c0ecb8bf28eb 21120 /*
Marko Mikulicic 0:c0ecb8bf28eb 21121 * mark a vector containing `val_t` values (*not pointers* to them)
Marko Mikulicic 0:c0ecb8bf28eb 21122 */
Marko Mikulicic 0:c0ecb8bf28eb 21123 static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec) {
Marko Mikulicic 0:c0ecb8bf28eb 21124 gc_mark_val_array(v7, (val_t *) vec->p, vec->len / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21125 }
Marko Mikulicic 0:c0ecb8bf28eb 21126
Marko Mikulicic 0:c0ecb8bf28eb 21127 /*
Marko Mikulicic 0:c0ecb8bf28eb 21128 * mark an mbuf containing foreign pointers to `struct bcode`
Marko Mikulicic 0:c0ecb8bf28eb 21129 */
Marko Mikulicic 0:c0ecb8bf28eb 21130 static void gc_mark_mbuf_bcode_pt(struct v7 *v7, const struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 21131 struct bcode **vp;
Marko Mikulicic 0:c0ecb8bf28eb 21132 for (vp = (struct bcode **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len;
Marko Mikulicic 0:c0ecb8bf28eb 21133 vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 21134 gc_mark_vec_val(v7, &(*vp)->lit);
Marko Mikulicic 0:c0ecb8bf28eb 21135 }
Marko Mikulicic 0:c0ecb8bf28eb 21136 }
Marko Mikulicic 0:c0ecb8bf28eb 21137
Marko Mikulicic 0:c0ecb8bf28eb 21138 static void gc_mark_call_stack_private(
Marko Mikulicic 0:c0ecb8bf28eb 21139 struct v7 *v7, struct v7_call_frame_private *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21140 gc_mark_val_array(v7, (val_t *) &call_stack->vals,
Marko Mikulicic 0:c0ecb8bf28eb 21141 sizeof(call_stack->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21142 }
Marko Mikulicic 0:c0ecb8bf28eb 21143
Marko Mikulicic 0:c0ecb8bf28eb 21144 static void gc_mark_call_stack_cfunc(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 21145 struct v7_call_frame_cfunc *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21146 gc_mark_val_array(v7, (val_t *) &call_stack->vals,
Marko Mikulicic 0:c0ecb8bf28eb 21147 sizeof(call_stack->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21148 }
Marko Mikulicic 0:c0ecb8bf28eb 21149
Marko Mikulicic 0:c0ecb8bf28eb 21150 static void gc_mark_call_stack_bcode(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 21151 struct v7_call_frame_bcode *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21152 gc_mark_val_array(v7, (val_t *) &call_stack->vals,
Marko Mikulicic 0:c0ecb8bf28eb 21153 sizeof(call_stack->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21154 }
Marko Mikulicic 0:c0ecb8bf28eb 21155
Marko Mikulicic 0:c0ecb8bf28eb 21156 /*
Marko Mikulicic 0:c0ecb8bf28eb 21157 * mark `struct v7_call_frame` and all its back-linked frames
Marko Mikulicic 0:c0ecb8bf28eb 21158 */
Marko Mikulicic 0:c0ecb8bf28eb 21159 static void gc_mark_call_stack(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 21160 struct v7_call_frame_base *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21161 while (call_stack != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 21162 if (call_stack->type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 21163 gc_mark_call_stack_bcode(v7, (struct v7_call_frame_bcode *) call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21164 }
Marko Mikulicic 0:c0ecb8bf28eb 21165
Marko Mikulicic 0:c0ecb8bf28eb 21166 if (call_stack->type_mask & V7_CALL_FRAME_MASK_PRIVATE) {
Marko Mikulicic 0:c0ecb8bf28eb 21167 gc_mark_call_stack_private(v7,
Marko Mikulicic 0:c0ecb8bf28eb 21168 (struct v7_call_frame_private *) call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21169 }
Marko Mikulicic 0:c0ecb8bf28eb 21170
Marko Mikulicic 0:c0ecb8bf28eb 21171 if (call_stack->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 21172 gc_mark_call_stack_cfunc(v7, (struct v7_call_frame_cfunc *) call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21173 }
Marko Mikulicic 0:c0ecb8bf28eb 21174
Marko Mikulicic 0:c0ecb8bf28eb 21175 call_stack = call_stack->prev;
Marko Mikulicic 0:c0ecb8bf28eb 21176 }
Marko Mikulicic 0:c0ecb8bf28eb 21177 }
Marko Mikulicic 0:c0ecb8bf28eb 21178
Marko Mikulicic 0:c0ecb8bf28eb 21179 /* Perform garbage collection */
Marko Mikulicic 0:c0ecb8bf28eb 21180 void v7_gc(struct v7 *v7, int full) {
Marko Mikulicic 0:c0ecb8bf28eb 21181 #ifdef V7_DISABLE_GC
Marko Mikulicic 0:c0ecb8bf28eb 21182 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 21183 (void) full;
Marko Mikulicic 0:c0ecb8bf28eb 21184 return;
Marko Mikulicic 0:c0ecb8bf28eb 21185 #else
Marko Mikulicic 0:c0ecb8bf28eb 21186
Marko Mikulicic 0:c0ecb8bf28eb 21187 #if defined(V7_GC_VERBOSE)
Marko Mikulicic 0:c0ecb8bf28eb 21188 fprintf(stderr, "V7 GC pass %d\n", ++gc_pass);
Marko Mikulicic 0:c0ecb8bf28eb 21189 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21190
Marko Mikulicic 0:c0ecb8bf28eb 21191 gc_dump_arena_stats("Before GC objects", &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21192 gc_dump_arena_stats("Before GC functions", &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21193 gc_dump_arena_stats("Before GC properties", &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21194
Marko Mikulicic 0:c0ecb8bf28eb 21195 gc_mark_call_stack(v7, v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21196
Marko Mikulicic 0:c0ecb8bf28eb 21197 gc_mark_val_array(v7, (val_t *) &v7->vals, sizeof(v7->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21198 /* mark all items on bcode stack */
Marko Mikulicic 0:c0ecb8bf28eb 21199 gc_mark_mbuf_val(v7, &v7->stack);
Marko Mikulicic 0:c0ecb8bf28eb 21200
Marko Mikulicic 0:c0ecb8bf28eb 21201 /* mark literals and names of all the active bcodes */
Marko Mikulicic 0:c0ecb8bf28eb 21202 gc_mark_mbuf_bcode_pt(v7, &v7->act_bcodes);
Marko Mikulicic 0:c0ecb8bf28eb 21203
Marko Mikulicic 0:c0ecb8bf28eb 21204 gc_mark_mbuf_pt(v7, &v7->tmp_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21205 gc_mark_mbuf_pt(v7, &v7->owned_values);
Marko Mikulicic 0:c0ecb8bf28eb 21206
Marko Mikulicic 0:c0ecb8bf28eb 21207 gc_compact_strings(v7);
Marko Mikulicic 0:c0ecb8bf28eb 21208
Marko Mikulicic 0:c0ecb8bf28eb 21209 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 21210 gc_sweep_malloc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 21211 #else
Marko Mikulicic 0:c0ecb8bf28eb 21212 gc_sweep(v7, &v7->generic_object_arena, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21213 gc_sweep(v7, &v7->function_arena, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21214 gc_sweep(v7, &v7->property_arena, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21215 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21216
Marko Mikulicic 0:c0ecb8bf28eb 21217 gc_dump_arena_stats("After GC objects", &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21218 gc_dump_arena_stats("After GC functions", &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21219 gc_dump_arena_stats("After GC properties", &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21220
Marko Mikulicic 0:c0ecb8bf28eb 21221 if (full) {
Marko Mikulicic 0:c0ecb8bf28eb 21222 /*
Marko Mikulicic 0:c0ecb8bf28eb 21223 * In case of full GC, we also resize strings buffer, but we still leave
Marko Mikulicic 0:c0ecb8bf28eb 21224 * some extra space (at most, `_V7_STRING_BUF_RESERVE`) in order to avoid
Marko Mikulicic 0:c0ecb8bf28eb 21225 * frequent reallocations
Marko Mikulicic 0:c0ecb8bf28eb 21226 */
Marko Mikulicic 0:c0ecb8bf28eb 21227 size_t trimmed_size = v7->owned_strings.len + _V7_STRING_BUF_RESERVE;
Marko Mikulicic 0:c0ecb8bf28eb 21228 if (trimmed_size < v7->owned_strings.size) {
Marko Mikulicic 0:c0ecb8bf28eb 21229 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 21230 mbuf_resize(&v7->owned_strings, trimmed_size);
Marko Mikulicic 0:c0ecb8bf28eb 21231 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 21232 }
Marko Mikulicic 0:c0ecb8bf28eb 21233 }
Marko Mikulicic 0:c0ecb8bf28eb 21234 #endif /* V7_DISABLE_GC */
Marko Mikulicic 0:c0ecb8bf28eb 21235 }
Marko Mikulicic 0:c0ecb8bf28eb 21236
Marko Mikulicic 0:c0ecb8bf28eb 21237 V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 21238 if (is_js_function(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 21239 return gc_check_ptr(&v7->function_arena, get_js_function_struct(v));
Marko Mikulicic 0:c0ecb8bf28eb 21240 } else if (v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 21241 return gc_check_ptr(&v7->generic_object_arena, get_object_struct(v));
Marko Mikulicic 0:c0ecb8bf28eb 21242 }
Marko Mikulicic 0:c0ecb8bf28eb 21243 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21244 }
Marko Mikulicic 0:c0ecb8bf28eb 21245
Marko Mikulicic 0:c0ecb8bf28eb 21246 V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 21247 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 21248 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 21249 (void) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 21250 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21251 #else
Marko Mikulicic 0:c0ecb8bf28eb 21252 const struct gc_cell *p = (const struct gc_cell *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 21253 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 21254 for (b = a->blocks; b != NULL; b = b->next) {
Marko Mikulicic 0:c0ecb8bf28eb 21255 if (p >= b->base && p < GC_CELL_OP(a, b->base, +, b->size)) {
Marko Mikulicic 0:c0ecb8bf28eb 21256 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21257 }
Marko Mikulicic 0:c0ecb8bf28eb 21258 }
Marko Mikulicic 0:c0ecb8bf28eb 21259 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 21260 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21261 }
Marko Mikulicic 0:c0ecb8bf28eb 21262 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 21263 #line 1 "v7/src/freeze.c"
Marko Mikulicic 0:c0ecb8bf28eb 21264 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21265 /*
Marko Mikulicic 0:c0ecb8bf28eb 21266 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 21267 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 21268 */
Marko Mikulicic 0:c0ecb8bf28eb 21269
Marko Mikulicic 0:c0ecb8bf28eb 21270 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21271 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21272 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21273 /* Amalgamated: #include "v7/src/freeze.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21274 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21275 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21276 /* Amalgamated: #include "common/base64.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21277 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21278
Marko Mikulicic 0:c0ecb8bf28eb 21279 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 21280
Marko Mikulicic 0:c0ecb8bf28eb 21281 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 21282
Marko Mikulicic 0:c0ecb8bf28eb 21283 V7_PRIVATE void freeze(struct v7 *v7, char *filename) {
Marko Mikulicic 0:c0ecb8bf28eb 21284 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 21285
Marko Mikulicic 0:c0ecb8bf28eb 21286 v7->freeze_file = fopen(filename, "w");
Marko Mikulicic 0:c0ecb8bf28eb 21287 assert(v7->freeze_file != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 21288
Marko Mikulicic 0:c0ecb8bf28eb 21289 #ifndef V7_FREEZE_NOT_READONLY
Marko Mikulicic 0:c0ecb8bf28eb 21290 /*
Marko Mikulicic 0:c0ecb8bf28eb 21291 * We have to remove `global` from the global object since
Marko Mikulicic 0:c0ecb8bf28eb 21292 * when thawing global will actually be a new mutable object
Marko Mikulicic 0:c0ecb8bf28eb 21293 * living on the heap.
Marko Mikulicic 0:c0ecb8bf28eb 21294 */
Marko Mikulicic 0:c0ecb8bf28eb 21295 v7_del(v7, v7->vals.global_object, "global", 6);
Marko Mikulicic 0:c0ecb8bf28eb 21296 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21297
Marko Mikulicic 0:c0ecb8bf28eb 21298 for (i = 0; i < sizeof(v7->vals) / sizeof(val_t); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 21299 val_t v = ((val_t *) &v7->vals)[i];
Marko Mikulicic 0:c0ecb8bf28eb 21300 fprintf(v7->freeze_file,
Marko Mikulicic 0:c0ecb8bf28eb 21301 "{\"type\":\"global\", \"idx\":%zu, \"value\":\"%p\"}\n", i,
Marko Mikulicic 0:c0ecb8bf28eb 21302 (void *) (v7_is_object(v) ? get_object_struct(v) : 0x0));
Marko Mikulicic 0:c0ecb8bf28eb 21303 }
Marko Mikulicic 0:c0ecb8bf28eb 21304
Marko Mikulicic 0:c0ecb8bf28eb 21305 /*
Marko Mikulicic 0:c0ecb8bf28eb 21306 * since v7->freeze_file is not NULL this will cause freeze_obj and
Marko Mikulicic 0:c0ecb8bf28eb 21307 * freeze_prop to be called for each reachable object and property.
Marko Mikulicic 0:c0ecb8bf28eb 21308 */
Marko Mikulicic 0:c0ecb8bf28eb 21309 v7_gc(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 21310 assert(v7->stack.len == 0);
Marko Mikulicic 0:c0ecb8bf28eb 21311
Marko Mikulicic 0:c0ecb8bf28eb 21312 fclose(v7->freeze_file);
Marko Mikulicic 0:c0ecb8bf28eb 21313 v7->freeze_file = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 21314 }
Marko Mikulicic 0:c0ecb8bf28eb 21315
Marko Mikulicic 0:c0ecb8bf28eb 21316 static char *freeze_vec(struct v7_vec *vec) {
Marko Mikulicic 0:c0ecb8bf28eb 21317 char *res = (char *) malloc(512 + vec->len);
Marko Mikulicic 0:c0ecb8bf28eb 21318 res[0] = '"';
Marko Mikulicic 0:c0ecb8bf28eb 21319 cs_base64_encode((const unsigned char *) vec->p, vec->len, &res[1]);
Marko Mikulicic 0:c0ecb8bf28eb 21320 strcat(res, "\"");
Marko Mikulicic 0:c0ecb8bf28eb 21321 return res;
Marko Mikulicic 0:c0ecb8bf28eb 21322 }
Marko Mikulicic 0:c0ecb8bf28eb 21323
Marko Mikulicic 0:c0ecb8bf28eb 21324 V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 21325 struct v7_object *obj_base = get_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 21326 unsigned int attrs = V7_OBJ_OFF_HEAP;
Marko Mikulicic 0:c0ecb8bf28eb 21327
Marko Mikulicic 0:c0ecb8bf28eb 21328 #ifndef V7_FREEZE_NOT_READONLY
Marko Mikulicic 0:c0ecb8bf28eb 21329 attrs |= V7_OBJ_NOT_EXTENSIBLE;
Marko Mikulicic 0:c0ecb8bf28eb 21330 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21331
Marko Mikulicic 0:c0ecb8bf28eb 21332 if (is_js_function(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 21333 struct v7_js_function *func = get_js_function_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 21334 struct bcode *bcode = func->bcode;
Marko Mikulicic 0:c0ecb8bf28eb 21335 char *jops = freeze_vec(&bcode->ops);
Marko Mikulicic 0:c0ecb8bf28eb 21336 int i;
Marko Mikulicic 0:c0ecb8bf28eb 21337
Marko Mikulicic 0:c0ecb8bf28eb 21338 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21339 "{\"type\":\"func\", \"addr\":\"%p\", \"props\":\"%p\", "
Marko Mikulicic 0:c0ecb8bf28eb 21340 "\"attrs\":%d, \"scope\":\"%p\", \"bcode\":\"%p\""
Marko Mikulicic 0:c0ecb8bf28eb 21341 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21342 ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" "
Marko Mikulicic 0:c0ecb8bf28eb 21343 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21344 "}\n",
Marko Mikulicic 0:c0ecb8bf28eb 21345 (void *) obj_base,
Marko Mikulicic 0:c0ecb8bf28eb 21346 (void *) ((uintptr_t) obj_base->properties & ~0x1),
Marko Mikulicic 0:c0ecb8bf28eb 21347 obj_base->attributes | attrs, (void *) func->scope, (void *) bcode
Marko Mikulicic 0:c0ecb8bf28eb 21348 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21349 ,
Marko Mikulicic 0:c0ecb8bf28eb 21350 obj_base->entity_id_base, obj_base->entity_id_spec
Marko Mikulicic 0:c0ecb8bf28eb 21351 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21352 );
Marko Mikulicic 0:c0ecb8bf28eb 21353 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21354 "{\"type\":\"bcode\", \"addr\":\"%p\", \"args_cnt\":%d, "
Marko Mikulicic 0:c0ecb8bf28eb 21355 "\"names_cnt\":%d, "
Marko Mikulicic 0:c0ecb8bf28eb 21356 "\"strict_mode\": %d, \"func_name_present\": %d, \"ops\":%s, "
Marko Mikulicic 0:c0ecb8bf28eb 21357 "\"lit\": [",
Marko Mikulicic 0:c0ecb8bf28eb 21358 (void *) bcode, bcode->args_cnt, bcode->names_cnt,
Marko Mikulicic 0:c0ecb8bf28eb 21359 bcode->strict_mode, bcode->func_name_present, jops);
Marko Mikulicic 0:c0ecb8bf28eb 21360
Marko Mikulicic 0:c0ecb8bf28eb 21361 for (i = 0; (size_t) i < bcode->lit.len / sizeof(val_t); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 21362 val_t v = ((val_t *) bcode->lit.p)[i];
Marko Mikulicic 0:c0ecb8bf28eb 21363 const char *str;
Marko Mikulicic 0:c0ecb8bf28eb 21364
Marko Mikulicic 0:c0ecb8bf28eb 21365 if (((v & V7_TAG_MASK) == V7_TAG_STRING_O ||
Marko Mikulicic 0:c0ecb8bf28eb 21366 (v & V7_TAG_MASK) == V7_TAG_STRING_F) &&
Marko Mikulicic 0:c0ecb8bf28eb 21367 (str = v7_get_cstring(v7, &v)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 21368 fprintf(f, "{\"str\": \"%s\"}", str);
Marko Mikulicic 0:c0ecb8bf28eb 21369 } else {
Marko Mikulicic 0:c0ecb8bf28eb 21370 fprintf(f, "{\"val\": \"0x%" INT64_X_FMT "\"}", v);
Marko Mikulicic 0:c0ecb8bf28eb 21371 }
Marko Mikulicic 0:c0ecb8bf28eb 21372 if ((size_t) i != bcode->lit.len / sizeof(val_t) - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 21373 fprintf(f, ",");
Marko Mikulicic 0:c0ecb8bf28eb 21374 }
Marko Mikulicic 0:c0ecb8bf28eb 21375 }
Marko Mikulicic 0:c0ecb8bf28eb 21376
Marko Mikulicic 0:c0ecb8bf28eb 21377 fprintf(f, "]}\n");
Marko Mikulicic 0:c0ecb8bf28eb 21378 free(jops);
Marko Mikulicic 0:c0ecb8bf28eb 21379 } else {
Marko Mikulicic 0:c0ecb8bf28eb 21380 struct v7_generic_object *gob = get_generic_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 21381 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21382 "{\"type\":\"obj\", \"addr\":\"%p\", \"props\":\"%p\", "
Marko Mikulicic 0:c0ecb8bf28eb 21383 "\"attrs\":%d, \"proto\":\"%p\""
Marko Mikulicic 0:c0ecb8bf28eb 21384 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21385 ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" "
Marko Mikulicic 0:c0ecb8bf28eb 21386 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21387 "}\n",
Marko Mikulicic 0:c0ecb8bf28eb 21388 (void *) obj_base,
Marko Mikulicic 0:c0ecb8bf28eb 21389 (void *) ((uintptr_t) obj_base->properties & ~0x1),
Marko Mikulicic 0:c0ecb8bf28eb 21390 obj_base->attributes | attrs, (void *) gob->prototype
Marko Mikulicic 0:c0ecb8bf28eb 21391 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21392 ,
Marko Mikulicic 0:c0ecb8bf28eb 21393 obj_base->entity_id_base, obj_base->entity_id_spec
Marko Mikulicic 0:c0ecb8bf28eb 21394 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21395 );
Marko Mikulicic 0:c0ecb8bf28eb 21396 }
Marko Mikulicic 0:c0ecb8bf28eb 21397 }
Marko Mikulicic 0:c0ecb8bf28eb 21398
Marko Mikulicic 0:c0ecb8bf28eb 21399 V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop) {
Marko Mikulicic 0:c0ecb8bf28eb 21400 unsigned int attrs = _V7_PROPERTY_OFF_HEAP;
Marko Mikulicic 0:c0ecb8bf28eb 21401 #ifndef V7_FREEZE_NOT_READONLY
Marko Mikulicic 0:c0ecb8bf28eb 21402 attrs |= V7_PROPERTY_NON_WRITABLE | V7_PROPERTY_NON_CONFIGURABLE;
Marko Mikulicic 0:c0ecb8bf28eb 21403 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21404
Marko Mikulicic 0:c0ecb8bf28eb 21405 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21406 "{\"type\":\"prop\","
Marko Mikulicic 0:c0ecb8bf28eb 21407 " \"addr\":\"%p\","
Marko Mikulicic 0:c0ecb8bf28eb 21408 " \"next\":\"%p\","
Marko Mikulicic 0:c0ecb8bf28eb 21409 " \"attrs\":%d,"
Marko Mikulicic 0:c0ecb8bf28eb 21410 " \"name\":\"0x%" INT64_X_FMT
Marko Mikulicic 0:c0ecb8bf28eb 21411 "\","
Marko Mikulicic 0:c0ecb8bf28eb 21412 " \"value_type\":%d,"
Marko Mikulicic 0:c0ecb8bf28eb 21413 " \"value\":\"0x%" INT64_X_FMT
Marko Mikulicic 0:c0ecb8bf28eb 21414 "\","
Marko Mikulicic 0:c0ecb8bf28eb 21415 " \"name_str\":\"%s\""
Marko Mikulicic 0:c0ecb8bf28eb 21416 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21417 ", \"entity_id\":\"%d\""
Marko Mikulicic 0:c0ecb8bf28eb 21418 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21419 "}\n",
Marko Mikulicic 0:c0ecb8bf28eb 21420 (void *) prop, (void *) prop->next, prop->attributes | attrs,
Marko Mikulicic 0:c0ecb8bf28eb 21421 prop->name, val_type(v7, prop->value), prop->value,
Marko Mikulicic 0:c0ecb8bf28eb 21422 v7_get_cstring(v7, &prop->name)
Marko Mikulicic 0:c0ecb8bf28eb 21423 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21424 ,
Marko Mikulicic 0:c0ecb8bf28eb 21425 prop->entity_id
Marko Mikulicic 0:c0ecb8bf28eb 21426 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21427 );
Marko Mikulicic 0:c0ecb8bf28eb 21428 }
Marko Mikulicic 0:c0ecb8bf28eb 21429
Marko Mikulicic 0:c0ecb8bf28eb 21430 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21431 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 21432 #line 1 "v7/src/parser.c"
Marko Mikulicic 0:c0ecb8bf28eb 21433 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21434 /*
Marko Mikulicic 0:c0ecb8bf28eb 21435 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 21436 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 21437 */
Marko Mikulicic 0:c0ecb8bf28eb 21438
Marko Mikulicic 0:c0ecb8bf28eb 21439 /* Amalgamated: #include "common/coroutine.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21440 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21441 /* Amalgamated: #include "v7/src/parser.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21442 /* Amalgamated: #include "v7/src/tokenizer.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21443 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21444 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21445 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21446 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21447 /* Amalgamated: #include "v7/src/cyg_profile.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21448
Marko Mikulicic 0:c0ecb8bf28eb 21449 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 21450
Marko Mikulicic 0:c0ecb8bf28eb 21451 #define ACCEPT(t) (((v7)->cur_tok == (t)) ? next_tok((v7)), 1 : 0)
Marko Mikulicic 0:c0ecb8bf28eb 21452
Marko Mikulicic 0:c0ecb8bf28eb 21453 #define EXPECT(t) \
Marko Mikulicic 0:c0ecb8bf28eb 21454 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21455 if ((v7)->cur_tok != (t)) { \
Marko Mikulicic 0:c0ecb8bf28eb 21456 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); \
Marko Mikulicic 0:c0ecb8bf28eb 21457 } \
Marko Mikulicic 0:c0ecb8bf28eb 21458 next_tok(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 21459 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21460
Marko Mikulicic 0:c0ecb8bf28eb 21461 #define PARSE_WITH_OPT_ARG(tag, arg_tag, arg_parser, label) \
Marko Mikulicic 0:c0ecb8bf28eb 21462 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21463 if (end_of_statement(v7) == V7_OK) { \
Marko Mikulicic 0:c0ecb8bf28eb 21464 add_node(v7, a, (tag)); \
Marko Mikulicic 0:c0ecb8bf28eb 21465 } else { \
Marko Mikulicic 0:c0ecb8bf28eb 21466 add_node(v7, a, (arg_tag)); \
Marko Mikulicic 0:c0ecb8bf28eb 21467 arg_parser(label); \
Marko Mikulicic 0:c0ecb8bf28eb 21468 } \
Marko Mikulicic 0:c0ecb8bf28eb 21469 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21470
Marko Mikulicic 0:c0ecb8bf28eb 21471 #define N (CR_ARG_RET_PT()->arg)
Marko Mikulicic 0:c0ecb8bf28eb 21472
Marko Mikulicic 0:c0ecb8bf28eb 21473 /*
Marko Mikulicic 0:c0ecb8bf28eb 21474 * User functions
Marko Mikulicic 0:c0ecb8bf28eb 21475 * (as well as other in-function entry points)
Marko Mikulicic 0:c0ecb8bf28eb 21476 */
Marko Mikulicic 0:c0ecb8bf28eb 21477 enum my_fid {
Marko Mikulicic 0:c0ecb8bf28eb 21478 fid_none = CR_FID__NONE,
Marko Mikulicic 0:c0ecb8bf28eb 21479
Marko Mikulicic 0:c0ecb8bf28eb 21480 /* parse_script function */
Marko Mikulicic 0:c0ecb8bf28eb 21481 fid_parse_script = CR_FID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 21482 fid_p_script_1,
Marko Mikulicic 0:c0ecb8bf28eb 21483 fid_p_script_2,
Marko Mikulicic 0:c0ecb8bf28eb 21484 fid_p_script_3,
Marko Mikulicic 0:c0ecb8bf28eb 21485 fid_p_script_4,
Marko Mikulicic 0:c0ecb8bf28eb 21486
Marko Mikulicic 0:c0ecb8bf28eb 21487 /* parse_use_strict function */
Marko Mikulicic 0:c0ecb8bf28eb 21488 fid_parse_use_strict,
Marko Mikulicic 0:c0ecb8bf28eb 21489
Marko Mikulicic 0:c0ecb8bf28eb 21490 /* parse_body function */
Marko Mikulicic 0:c0ecb8bf28eb 21491 fid_parse_body,
Marko Mikulicic 0:c0ecb8bf28eb 21492 fid_p_body_1,
Marko Mikulicic 0:c0ecb8bf28eb 21493 fid_p_body_2,
Marko Mikulicic 0:c0ecb8bf28eb 21494
Marko Mikulicic 0:c0ecb8bf28eb 21495 /* parse_statement function */
Marko Mikulicic 0:c0ecb8bf28eb 21496 fid_parse_statement,
Marko Mikulicic 0:c0ecb8bf28eb 21497 fid_p_stat_1,
Marko Mikulicic 0:c0ecb8bf28eb 21498 fid_p_stat_2,
Marko Mikulicic 0:c0ecb8bf28eb 21499 fid_p_stat_3,
Marko Mikulicic 0:c0ecb8bf28eb 21500 fid_p_stat_4,
Marko Mikulicic 0:c0ecb8bf28eb 21501 fid_p_stat_5,
Marko Mikulicic 0:c0ecb8bf28eb 21502 fid_p_stat_6,
Marko Mikulicic 0:c0ecb8bf28eb 21503 fid_p_stat_7,
Marko Mikulicic 0:c0ecb8bf28eb 21504 fid_p_stat_8,
Marko Mikulicic 0:c0ecb8bf28eb 21505 fid_p_stat_9,
Marko Mikulicic 0:c0ecb8bf28eb 21506 fid_p_stat_10,
Marko Mikulicic 0:c0ecb8bf28eb 21507 fid_p_stat_11,
Marko Mikulicic 0:c0ecb8bf28eb 21508 fid_p_stat_12,
Marko Mikulicic 0:c0ecb8bf28eb 21509 fid_p_stat_13,
Marko Mikulicic 0:c0ecb8bf28eb 21510 fid_p_stat_14,
Marko Mikulicic 0:c0ecb8bf28eb 21511
Marko Mikulicic 0:c0ecb8bf28eb 21512 /* parse_expression function */
Marko Mikulicic 0:c0ecb8bf28eb 21513 fid_parse_expression,
Marko Mikulicic 0:c0ecb8bf28eb 21514 fid_p_expr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21515
Marko Mikulicic 0:c0ecb8bf28eb 21516 /* parse_assign function */
Marko Mikulicic 0:c0ecb8bf28eb 21517 fid_parse_assign,
Marko Mikulicic 0:c0ecb8bf28eb 21518 fid_p_assign_1,
Marko Mikulicic 0:c0ecb8bf28eb 21519
Marko Mikulicic 0:c0ecb8bf28eb 21520 /* parse_binary function */
Marko Mikulicic 0:c0ecb8bf28eb 21521 fid_parse_binary,
Marko Mikulicic 0:c0ecb8bf28eb 21522 fid_p_binary_1,
Marko Mikulicic 0:c0ecb8bf28eb 21523 fid_p_binary_2,
Marko Mikulicic 0:c0ecb8bf28eb 21524 fid_p_binary_3,
Marko Mikulicic 0:c0ecb8bf28eb 21525 fid_p_binary_4,
Marko Mikulicic 0:c0ecb8bf28eb 21526 fid_p_binary_5,
Marko Mikulicic 0:c0ecb8bf28eb 21527 fid_p_binary_6,
Marko Mikulicic 0:c0ecb8bf28eb 21528
Marko Mikulicic 0:c0ecb8bf28eb 21529 /* parse_prefix function */
Marko Mikulicic 0:c0ecb8bf28eb 21530 fid_parse_prefix,
Marko Mikulicic 0:c0ecb8bf28eb 21531 fid_p_prefix_1,
Marko Mikulicic 0:c0ecb8bf28eb 21532
Marko Mikulicic 0:c0ecb8bf28eb 21533 /* parse_postfix function */
Marko Mikulicic 0:c0ecb8bf28eb 21534 fid_parse_postfix,
Marko Mikulicic 0:c0ecb8bf28eb 21535 fid_p_postfix_1,
Marko Mikulicic 0:c0ecb8bf28eb 21536
Marko Mikulicic 0:c0ecb8bf28eb 21537 /* parse_callexpr function */
Marko Mikulicic 0:c0ecb8bf28eb 21538 fid_parse_callexpr,
Marko Mikulicic 0:c0ecb8bf28eb 21539 fid_p_callexpr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21540 fid_p_callexpr_2,
Marko Mikulicic 0:c0ecb8bf28eb 21541 fid_p_callexpr_3,
Marko Mikulicic 0:c0ecb8bf28eb 21542
Marko Mikulicic 0:c0ecb8bf28eb 21543 /* parse_newexpr function */
Marko Mikulicic 0:c0ecb8bf28eb 21544 fid_parse_newexpr,
Marko Mikulicic 0:c0ecb8bf28eb 21545 fid_p_newexpr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21546 fid_p_newexpr_2,
Marko Mikulicic 0:c0ecb8bf28eb 21547 fid_p_newexpr_3,
Marko Mikulicic 0:c0ecb8bf28eb 21548 fid_p_newexpr_4,
Marko Mikulicic 0:c0ecb8bf28eb 21549
Marko Mikulicic 0:c0ecb8bf28eb 21550 /* parse_terminal function */
Marko Mikulicic 0:c0ecb8bf28eb 21551 fid_parse_terminal,
Marko Mikulicic 0:c0ecb8bf28eb 21552 fid_p_terminal_1,
Marko Mikulicic 0:c0ecb8bf28eb 21553 fid_p_terminal_2,
Marko Mikulicic 0:c0ecb8bf28eb 21554 fid_p_terminal_3,
Marko Mikulicic 0:c0ecb8bf28eb 21555 fid_p_terminal_4,
Marko Mikulicic 0:c0ecb8bf28eb 21556
Marko Mikulicic 0:c0ecb8bf28eb 21557 /* parse_block function */
Marko Mikulicic 0:c0ecb8bf28eb 21558 fid_parse_block,
Marko Mikulicic 0:c0ecb8bf28eb 21559 fid_p_block_1,
Marko Mikulicic 0:c0ecb8bf28eb 21560
Marko Mikulicic 0:c0ecb8bf28eb 21561 /* parse_if function */
Marko Mikulicic 0:c0ecb8bf28eb 21562 fid_parse_if,
Marko Mikulicic 0:c0ecb8bf28eb 21563 fid_p_if_1,
Marko Mikulicic 0:c0ecb8bf28eb 21564 fid_p_if_2,
Marko Mikulicic 0:c0ecb8bf28eb 21565 fid_p_if_3,
Marko Mikulicic 0:c0ecb8bf28eb 21566
Marko Mikulicic 0:c0ecb8bf28eb 21567 /* parse_while function */
Marko Mikulicic 0:c0ecb8bf28eb 21568 fid_parse_while,
Marko Mikulicic 0:c0ecb8bf28eb 21569 fid_p_while_1,
Marko Mikulicic 0:c0ecb8bf28eb 21570 fid_p_while_2,
Marko Mikulicic 0:c0ecb8bf28eb 21571
Marko Mikulicic 0:c0ecb8bf28eb 21572 /* parse_ident function */
Marko Mikulicic 0:c0ecb8bf28eb 21573 fid_parse_ident,
Marko Mikulicic 0:c0ecb8bf28eb 21574
Marko Mikulicic 0:c0ecb8bf28eb 21575 /* parse_ident_allow_reserved_words function */
Marko Mikulicic 0:c0ecb8bf28eb 21576 fid_parse_ident_allow_reserved_words,
Marko Mikulicic 0:c0ecb8bf28eb 21577 fid_p_ident_arw_1,
Marko Mikulicic 0:c0ecb8bf28eb 21578
Marko Mikulicic 0:c0ecb8bf28eb 21579 /* parse_funcdecl function */
Marko Mikulicic 0:c0ecb8bf28eb 21580 fid_parse_funcdecl,
Marko Mikulicic 0:c0ecb8bf28eb 21581 fid_p_funcdecl_1,
Marko Mikulicic 0:c0ecb8bf28eb 21582 fid_p_funcdecl_2,
Marko Mikulicic 0:c0ecb8bf28eb 21583 fid_p_funcdecl_3,
Marko Mikulicic 0:c0ecb8bf28eb 21584 fid_p_funcdecl_4,
Marko Mikulicic 0:c0ecb8bf28eb 21585 fid_p_funcdecl_5,
Marko Mikulicic 0:c0ecb8bf28eb 21586 fid_p_funcdecl_6,
Marko Mikulicic 0:c0ecb8bf28eb 21587 fid_p_funcdecl_7,
Marko Mikulicic 0:c0ecb8bf28eb 21588 fid_p_funcdecl_8,
Marko Mikulicic 0:c0ecb8bf28eb 21589 fid_p_funcdecl_9,
Marko Mikulicic 0:c0ecb8bf28eb 21590
Marko Mikulicic 0:c0ecb8bf28eb 21591 /* parse_arglist function */
Marko Mikulicic 0:c0ecb8bf28eb 21592 fid_parse_arglist,
Marko Mikulicic 0:c0ecb8bf28eb 21593 fid_p_arglist_1,
Marko Mikulicic 0:c0ecb8bf28eb 21594
Marko Mikulicic 0:c0ecb8bf28eb 21595 /* parse_member function */
Marko Mikulicic 0:c0ecb8bf28eb 21596 fid_parse_member,
Marko Mikulicic 0:c0ecb8bf28eb 21597 fid_p_member_1,
Marko Mikulicic 0:c0ecb8bf28eb 21598
Marko Mikulicic 0:c0ecb8bf28eb 21599 /* parse_memberexpr function */
Marko Mikulicic 0:c0ecb8bf28eb 21600 fid_parse_memberexpr,
Marko Mikulicic 0:c0ecb8bf28eb 21601 fid_p_memberexpr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21602 fid_p_memberexpr_2,
Marko Mikulicic 0:c0ecb8bf28eb 21603
Marko Mikulicic 0:c0ecb8bf28eb 21604 /* parse_var function */
Marko Mikulicic 0:c0ecb8bf28eb 21605 fid_parse_var,
Marko Mikulicic 0:c0ecb8bf28eb 21606 fid_p_var_1,
Marko Mikulicic 0:c0ecb8bf28eb 21607
Marko Mikulicic 0:c0ecb8bf28eb 21608 /* parse_prop function */
Marko Mikulicic 0:c0ecb8bf28eb 21609 fid_parse_prop,
Marko Mikulicic 0:c0ecb8bf28eb 21610 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 21611 fid_p_prop_1_getter,
Marko Mikulicic 0:c0ecb8bf28eb 21612 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21613 fid_p_prop_2,
Marko Mikulicic 0:c0ecb8bf28eb 21614 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 21615 fid_p_prop_3_setter,
Marko Mikulicic 0:c0ecb8bf28eb 21616 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21617 fid_p_prop_4,
Marko Mikulicic 0:c0ecb8bf28eb 21618
Marko Mikulicic 0:c0ecb8bf28eb 21619 /* parse_dowhile function */
Marko Mikulicic 0:c0ecb8bf28eb 21620 fid_parse_dowhile,
Marko Mikulicic 0:c0ecb8bf28eb 21621 fid_p_dowhile_1,
Marko Mikulicic 0:c0ecb8bf28eb 21622 fid_p_dowhile_2,
Marko Mikulicic 0:c0ecb8bf28eb 21623
Marko Mikulicic 0:c0ecb8bf28eb 21624 /* parse_for function */
Marko Mikulicic 0:c0ecb8bf28eb 21625 fid_parse_for,
Marko Mikulicic 0:c0ecb8bf28eb 21626 fid_p_for_1,
Marko Mikulicic 0:c0ecb8bf28eb 21627 fid_p_for_2,
Marko Mikulicic 0:c0ecb8bf28eb 21628 fid_p_for_3,
Marko Mikulicic 0:c0ecb8bf28eb 21629 fid_p_for_4,
Marko Mikulicic 0:c0ecb8bf28eb 21630 fid_p_for_5,
Marko Mikulicic 0:c0ecb8bf28eb 21631 fid_p_for_6,
Marko Mikulicic 0:c0ecb8bf28eb 21632
Marko Mikulicic 0:c0ecb8bf28eb 21633 /* parse_try function */
Marko Mikulicic 0:c0ecb8bf28eb 21634 fid_parse_try,
Marko Mikulicic 0:c0ecb8bf28eb 21635 fid_p_try_1,
Marko Mikulicic 0:c0ecb8bf28eb 21636 fid_p_try_2,
Marko Mikulicic 0:c0ecb8bf28eb 21637 fid_p_try_3,
Marko Mikulicic 0:c0ecb8bf28eb 21638 fid_p_try_4,
Marko Mikulicic 0:c0ecb8bf28eb 21639
Marko Mikulicic 0:c0ecb8bf28eb 21640 /* parse_switch function */
Marko Mikulicic 0:c0ecb8bf28eb 21641 fid_parse_switch,
Marko Mikulicic 0:c0ecb8bf28eb 21642 fid_p_switch_1,
Marko Mikulicic 0:c0ecb8bf28eb 21643 fid_p_switch_2,
Marko Mikulicic 0:c0ecb8bf28eb 21644 fid_p_switch_3,
Marko Mikulicic 0:c0ecb8bf28eb 21645 fid_p_switch_4,
Marko Mikulicic 0:c0ecb8bf28eb 21646
Marko Mikulicic 0:c0ecb8bf28eb 21647 /* parse_with function */
Marko Mikulicic 0:c0ecb8bf28eb 21648 fid_parse_with,
Marko Mikulicic 0:c0ecb8bf28eb 21649 fid_p_with_1,
Marko Mikulicic 0:c0ecb8bf28eb 21650 fid_p_with_2,
Marko Mikulicic 0:c0ecb8bf28eb 21651
Marko Mikulicic 0:c0ecb8bf28eb 21652 MY_FID_CNT
Marko Mikulicic 0:c0ecb8bf28eb 21653 };
Marko Mikulicic 0:c0ecb8bf28eb 21654
Marko Mikulicic 0:c0ecb8bf28eb 21655 /*
Marko Mikulicic 0:c0ecb8bf28eb 21656 * User exception IDs. The first one should have value `CR_EXC_ID__USER`
Marko Mikulicic 0:c0ecb8bf28eb 21657 */
Marko Mikulicic 0:c0ecb8bf28eb 21658 enum parser_exc_id {
Marko Mikulicic 0:c0ecb8bf28eb 21659 PARSER_EXC_ID__NONE = CR_EXC_ID__NONE,
Marko Mikulicic 0:c0ecb8bf28eb 21660 PARSER_EXC_ID__SYNTAX_ERROR = CR_EXC_ID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 21661 };
Marko Mikulicic 0:c0ecb8bf28eb 21662
Marko Mikulicic 0:c0ecb8bf28eb 21663 /* structures with locals and args {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21664
Marko Mikulicic 0:c0ecb8bf28eb 21665 /* parse_script {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21666
Marko Mikulicic 0:c0ecb8bf28eb 21667 /* parse_script's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21668 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21669 typedef struct fid_parse_script_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21670 } fid_parse_script_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21671 #else
Marko Mikulicic 0:c0ecb8bf28eb 21672 typedef cr_zero_size_type_t fid_parse_script_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21673 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21674
Marko Mikulicic 0:c0ecb8bf28eb 21675 /* parse_script's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21676 typedef struct fid_parse_script_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21677 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21678 struct fid_parse_script_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21679 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21680
Marko Mikulicic 0:c0ecb8bf28eb 21681 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21682 ast_off_t outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 21683 int saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 21684 } fid_parse_script_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21685
Marko Mikulicic 0:c0ecb8bf28eb 21686 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21687
Marko Mikulicic 0:c0ecb8bf28eb 21688 /* parse_use_strict {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21689 /* parse_use_strict's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21690 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21691 typedef struct fid_parse_use_strict_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21692 } fid_parse_use_strict_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21693 #else
Marko Mikulicic 0:c0ecb8bf28eb 21694 typedef cr_zero_size_type_t fid_parse_use_strict_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21695 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21696
Marko Mikulicic 0:c0ecb8bf28eb 21697 /* parse_use_strict's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21698 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21699 typedef struct fid_parse_use_strict_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21700 struct fid_parse_use_strict_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21701 } fid_parse_use_strict_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21702 #else
Marko Mikulicic 0:c0ecb8bf28eb 21703 typedef cr_zero_size_type_t fid_parse_use_strict_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21704 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21705
Marko Mikulicic 0:c0ecb8bf28eb 21706 #define CALL_PARSE_USE_STRICT(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21707 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21708 CR_CALL(fid_parse_use_strict, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21709 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21710
Marko Mikulicic 0:c0ecb8bf28eb 21711 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21712
Marko Mikulicic 0:c0ecb8bf28eb 21713 /* parse_body {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21714 /* parse_body's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21715 typedef struct fid_parse_body_arg { enum v7_tok end; } fid_parse_body_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21716
Marko Mikulicic 0:c0ecb8bf28eb 21717 /* parse_body's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21718 typedef struct fid_parse_body_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21719 struct fid_parse_body_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21720
Marko Mikulicic 0:c0ecb8bf28eb 21721 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21722 } fid_parse_body_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21723
Marko Mikulicic 0:c0ecb8bf28eb 21724 #define CALL_PARSE_BODY(_end, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 21725 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21726 N.fid_parse_body.end = (_end); \
Marko Mikulicic 0:c0ecb8bf28eb 21727 CR_CALL(fid_parse_body, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21728 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21729 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21730
Marko Mikulicic 0:c0ecb8bf28eb 21731 /* parse_statement {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21732 /* parse_statement's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21733 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21734 typedef struct fid_parse_statement_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21735 } fid_parse_statement_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21736 #else
Marko Mikulicic 0:c0ecb8bf28eb 21737 typedef cr_zero_size_type_t fid_parse_statement_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21738 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21739
Marko Mikulicic 0:c0ecb8bf28eb 21740 /* parse_statement's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21741 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21742 typedef struct fid_parse_statement_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21743 struct fid_parse_statement_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21744 } fid_parse_statement_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21745 #else
Marko Mikulicic 0:c0ecb8bf28eb 21746 typedef cr_zero_size_type_t fid_parse_statement_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21747 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21748
Marko Mikulicic 0:c0ecb8bf28eb 21749 #define CALL_PARSE_STATEMENT(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21750 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21751 CR_CALL(fid_parse_statement, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21752 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21753 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21754
Marko Mikulicic 0:c0ecb8bf28eb 21755 /* parse_expression {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21756 /* parse_expression's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21757 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21758 typedef struct fid_parse_expression_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21759 } fid_parse_expression_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21760 #else
Marko Mikulicic 0:c0ecb8bf28eb 21761 typedef cr_zero_size_type_t fid_parse_expression_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21762 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21763
Marko Mikulicic 0:c0ecb8bf28eb 21764 /* parse_expression's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21765 typedef struct fid_parse_expression_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21766 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21767 struct fid_parse_expression_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21768 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21769
Marko Mikulicic 0:c0ecb8bf28eb 21770 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21771 int group;
Marko Mikulicic 0:c0ecb8bf28eb 21772 } fid_parse_expression_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21773
Marko Mikulicic 0:c0ecb8bf28eb 21774 #define CALL_PARSE_EXPRESSION(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21775 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21776 CR_CALL(fid_parse_expression, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21777 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21778 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21779
Marko Mikulicic 0:c0ecb8bf28eb 21780 /* parse_assign {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21781 /* parse_assign's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21782 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21783 typedef struct fid_parse_assign_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21784 } fid_parse_assign_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21785 #else
Marko Mikulicic 0:c0ecb8bf28eb 21786 typedef cr_zero_size_type_t fid_parse_assign_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21787 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21788
Marko Mikulicic 0:c0ecb8bf28eb 21789 /* parse_assign's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21790 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21791 typedef struct fid_parse_assign_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21792 struct fid_parse_assign_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21793 } fid_parse_assign_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21794 #else
Marko Mikulicic 0:c0ecb8bf28eb 21795 typedef cr_zero_size_type_t fid_parse_assign_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21796 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21797
Marko Mikulicic 0:c0ecb8bf28eb 21798 #define CALL_PARSE_ASSIGN(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21799 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21800 CR_CALL(fid_parse_assign, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21801 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21802 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21803
Marko Mikulicic 0:c0ecb8bf28eb 21804 /* parse_binary {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21805 /* parse_binary's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21806 typedef struct fid_parse_binary_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21807 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21808 uint8_t min_level;
Marko Mikulicic 0:c0ecb8bf28eb 21809 } fid_parse_binary_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21810
Marko Mikulicic 0:c0ecb8bf28eb 21811 /* parse_binary's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21812 typedef struct fid_parse_binary_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21813 struct fid_parse_binary_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21814
Marko Mikulicic 0:c0ecb8bf28eb 21815 uint8_t i;
Marko Mikulicic 0:c0ecb8bf28eb 21816 /* during iteration, it becomes negative, so should be signed */
Marko Mikulicic 0:c0ecb8bf28eb 21817 int8_t level;
Marko Mikulicic 0:c0ecb8bf28eb 21818 uint8_t /*enum v7_tok*/ tok;
Marko Mikulicic 0:c0ecb8bf28eb 21819 uint8_t /*enum ast_tag*/ ast;
Marko Mikulicic 0:c0ecb8bf28eb 21820 ast_off_t saved_mbuf_len;
Marko Mikulicic 0:c0ecb8bf28eb 21821 } fid_parse_binary_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21822
Marko Mikulicic 0:c0ecb8bf28eb 21823 #define CALL_PARSE_BINARY(_level, _pos, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 21824 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21825 N.fid_parse_binary.min_level = (_level); \
Marko Mikulicic 0:c0ecb8bf28eb 21826 N.fid_parse_binary.pos = (_pos); \
Marko Mikulicic 0:c0ecb8bf28eb 21827 CR_CALL(fid_parse_binary, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21828 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21829 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21830
Marko Mikulicic 0:c0ecb8bf28eb 21831 /* parse_prefix {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21832 /* parse_prefix's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21833 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21834 typedef struct fid_parse_prefix_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21835 } fid_parse_prefix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21836 #else
Marko Mikulicic 0:c0ecb8bf28eb 21837 typedef cr_zero_size_type_t fid_parse_prefix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21838 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21839
Marko Mikulicic 0:c0ecb8bf28eb 21840 /* parse_prefix's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21841 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21842 typedef struct fid_parse_prefix_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21843 struct fid_parse_prefix_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21844 } fid_parse_prefix_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21845 #else
Marko Mikulicic 0:c0ecb8bf28eb 21846 typedef cr_zero_size_type_t fid_parse_prefix_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21847 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21848
Marko Mikulicic 0:c0ecb8bf28eb 21849 #define CALL_PARSE_PREFIX(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21850 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21851 CR_CALL(fid_parse_prefix, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21852 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21853 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21854
Marko Mikulicic 0:c0ecb8bf28eb 21855 /* parse_postfix {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21856 /* parse_postfix's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21857 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21858 typedef struct fid_parse_postfix_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21859 } fid_parse_postfix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21860 #else
Marko Mikulicic 0:c0ecb8bf28eb 21861 typedef cr_zero_size_type_t fid_parse_postfix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21862 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21863
Marko Mikulicic 0:c0ecb8bf28eb 21864 /* parse_postfix's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21865 typedef struct fid_parse_postfix_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21866 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21867 struct fid_parse_postfix_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21868 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21869
Marko Mikulicic 0:c0ecb8bf28eb 21870 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21871 } fid_parse_postfix_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21872
Marko Mikulicic 0:c0ecb8bf28eb 21873 #define CALL_PARSE_POSTFIX(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21874 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21875 CR_CALL(fid_parse_postfix, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21876 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21877 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21878
Marko Mikulicic 0:c0ecb8bf28eb 21879 /* parse_callexpr {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21880 /* parse_callexpr's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21881 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21882 typedef struct fid_parse_callexpr_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21883 } fid_parse_callexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21884 #else
Marko Mikulicic 0:c0ecb8bf28eb 21885 typedef cr_zero_size_type_t fid_parse_callexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21886 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21887
Marko Mikulicic 0:c0ecb8bf28eb 21888 /* parse_callexpr's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21889 typedef struct fid_parse_callexpr_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21890 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21891 struct fid_parse_callexpr_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21892 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21893
Marko Mikulicic 0:c0ecb8bf28eb 21894 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21895 } fid_parse_callexpr_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21896
Marko Mikulicic 0:c0ecb8bf28eb 21897 #define CALL_PARSE_CALLEXPR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21898 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21899 CR_CALL(fid_parse_callexpr, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21900 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21901 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21902
Marko Mikulicic 0:c0ecb8bf28eb 21903 /* parse_newexpr {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21904 /* parse_newexpr's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21905 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21906 typedef struct fid_parse_newexpr_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21907 } fid_parse_newexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21908 #else
Marko Mikulicic 0:c0ecb8bf28eb 21909 typedef cr_zero_size_type_t fid_parse_newexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21910 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21911
Marko Mikulicic 0:c0ecb8bf28eb 21912 /* parse_newexpr's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21913 typedef struct fid_parse_newexpr_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21914 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21915 struct fid_parse_newexpr_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21916 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21917
Marko Mikulicic 0:c0ecb8bf28eb 21918 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21919 } fid_parse_newexpr_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21920
Marko Mikulicic 0:c0ecb8bf28eb 21921 #define CALL_PARSE_NEWEXPR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21922 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21923 CR_CALL(fid_parse_newexpr, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21924 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21925 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21926
Marko Mikulicic 0:c0ecb8bf28eb 21927 /* parse_terminal {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21928 /* parse_terminal's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21929 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21930 typedef struct fid_parse_terminal_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21931 } fid_parse_terminal_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21932 #else
Marko Mikulicic 0:c0ecb8bf28eb 21933 typedef cr_zero_size_type_t fid_parse_terminal_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21934 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21935
Marko Mikulicic 0:c0ecb8bf28eb 21936 /* parse_terminal's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21937 typedef struct fid_parse_terminal_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21938 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21939 struct fid_parse_terminal_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21940 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21941
Marko Mikulicic 0:c0ecb8bf28eb 21942 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21943 } fid_parse_terminal_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21944
Marko Mikulicic 0:c0ecb8bf28eb 21945 #define CALL_PARSE_TERMINAL(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21946 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21947 CR_CALL(fid_parse_terminal, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21948 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21949 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21950
Marko Mikulicic 0:c0ecb8bf28eb 21951 /* parse_block {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21952 /* parse_block's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21953 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21954 typedef struct fid_parse_block_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21955 } fid_parse_block_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21956 #else
Marko Mikulicic 0:c0ecb8bf28eb 21957 typedef cr_zero_size_type_t fid_parse_block_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21958 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21959
Marko Mikulicic 0:c0ecb8bf28eb 21960 /* parse_block's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21961 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21962 typedef struct fid_parse_block_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21963 struct fid_parse_block_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21964 } fid_parse_block_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21965 #else
Marko Mikulicic 0:c0ecb8bf28eb 21966 typedef cr_zero_size_type_t fid_parse_block_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21967 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21968
Marko Mikulicic 0:c0ecb8bf28eb 21969 #define CALL_PARSE_BLOCK(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21970 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21971 CR_CALL(fid_parse_block, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21972 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21973 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21974
Marko Mikulicic 0:c0ecb8bf28eb 21975 /* parse_if {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21976 /* parse_if's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21977 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21978 typedef struct fid_parse_if_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21979 } fid_parse_if_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21980 #else
Marko Mikulicic 0:c0ecb8bf28eb 21981 typedef cr_zero_size_type_t fid_parse_if_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21982 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21983
Marko Mikulicic 0:c0ecb8bf28eb 21984 /* parse_if's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21985 typedef struct fid_parse_if_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21986 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21987 struct fid_parse_if_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21988 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21989
Marko Mikulicic 0:c0ecb8bf28eb 21990 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21991 } fid_parse_if_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21992
Marko Mikulicic 0:c0ecb8bf28eb 21993 #define CALL_PARSE_IF(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21994 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21995 CR_CALL(fid_parse_if, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21996 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21997 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21998
Marko Mikulicic 0:c0ecb8bf28eb 21999 /* parse_while {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22000 /* parse_while's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22001 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22002 typedef struct fid_parse_while_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22003 } fid_parse_while_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22004 #else
Marko Mikulicic 0:c0ecb8bf28eb 22005 typedef cr_zero_size_type_t fid_parse_while_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22006 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22007
Marko Mikulicic 0:c0ecb8bf28eb 22008 /* parse_while's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22009 typedef struct fid_parse_while_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22010 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22011 struct fid_parse_while_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22012 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22013
Marko Mikulicic 0:c0ecb8bf28eb 22014 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22015 uint8_t saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 22016 } fid_parse_while_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22017
Marko Mikulicic 0:c0ecb8bf28eb 22018 #define CALL_PARSE_WHILE(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22019 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22020 CR_CALL(fid_parse_while, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22021 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22022 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22023
Marko Mikulicic 0:c0ecb8bf28eb 22024 /* parse_ident {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22025 /* parse_ident's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22026 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22027 typedef struct fid_parse_ident_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22028 } fid_parse_ident_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22029 #else
Marko Mikulicic 0:c0ecb8bf28eb 22030 typedef cr_zero_size_type_t fid_parse_ident_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22031 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22032
Marko Mikulicic 0:c0ecb8bf28eb 22033 /* parse_ident's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22034 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22035 typedef struct fid_parse_ident_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22036 struct fid_parse_ident_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22037 } fid_parse_ident_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22038 #else
Marko Mikulicic 0:c0ecb8bf28eb 22039 typedef cr_zero_size_type_t fid_parse_ident_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22040 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22041
Marko Mikulicic 0:c0ecb8bf28eb 22042 #define CALL_PARSE_IDENT(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22043 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22044 CR_CALL(fid_parse_ident, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22045 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22046 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22047
Marko Mikulicic 0:c0ecb8bf28eb 22048 /* parse_ident_allow_reserved_words {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22049 /* parse_ident_allow_reserved_words's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22050 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22051 typedef struct fid_parse_ident_allow_reserved_words_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22052 } fid_parse_ident_allow_reserved_words_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22053 #else
Marko Mikulicic 0:c0ecb8bf28eb 22054 typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22055 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22056
Marko Mikulicic 0:c0ecb8bf28eb 22057 /* parse_ident_allow_reserved_words's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22058 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22059 typedef struct fid_parse_ident_allow_reserved_words_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22060 struct fid_parse_ident_allow_reserved_words_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22061 } fid_parse_ident_allow_reserved_words_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22062 #else
Marko Mikulicic 0:c0ecb8bf28eb 22063 typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22064 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22065
Marko Mikulicic 0:c0ecb8bf28eb 22066 #define CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22067 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22068 CR_CALL(fid_parse_ident_allow_reserved_words, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22069 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22070 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22071
Marko Mikulicic 0:c0ecb8bf28eb 22072 /* parse_funcdecl {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22073 /* parse_funcdecl's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22074 typedef struct fid_parse_funcdecl_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22075 uint8_t require_named;
Marko Mikulicic 0:c0ecb8bf28eb 22076 uint8_t reserved_name;
Marko Mikulicic 0:c0ecb8bf28eb 22077 } fid_parse_funcdecl_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22078
Marko Mikulicic 0:c0ecb8bf28eb 22079 /* parse_funcdecl's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22080 typedef struct fid_parse_funcdecl_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22081 struct fid_parse_funcdecl_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22082
Marko Mikulicic 0:c0ecb8bf28eb 22083 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22084 ast_off_t outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 22085 uint8_t saved_in_function;
Marko Mikulicic 0:c0ecb8bf28eb 22086 uint8_t saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22087 } fid_parse_funcdecl_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22088
Marko Mikulicic 0:c0ecb8bf28eb 22089 #define CALL_PARSE_FUNCDECL(_require_named, _reserved_name, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 22090 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22091 N.fid_parse_funcdecl.require_named = (_require_named); \
Marko Mikulicic 0:c0ecb8bf28eb 22092 N.fid_parse_funcdecl.reserved_name = (_reserved_name); \
Marko Mikulicic 0:c0ecb8bf28eb 22093 CR_CALL(fid_parse_funcdecl, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22094 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22095 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22096
Marko Mikulicic 0:c0ecb8bf28eb 22097 /* parse_arglist {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22098 /* parse_arglist's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22099 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22100 typedef struct fid_parse_arglist_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22101 } fid_parse_arglist_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22102 #else
Marko Mikulicic 0:c0ecb8bf28eb 22103 typedef cr_zero_size_type_t fid_parse_arglist_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22104 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22105
Marko Mikulicic 0:c0ecb8bf28eb 22106 /* parse_arglist's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22107 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22108 typedef struct fid_parse_arglist_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22109 struct fid_parse_arglist_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22110 } fid_parse_arglist_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22111 #else
Marko Mikulicic 0:c0ecb8bf28eb 22112 typedef cr_zero_size_type_t fid_parse_arglist_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22113 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22114
Marko Mikulicic 0:c0ecb8bf28eb 22115 #define CALL_PARSE_ARGLIST(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22116 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22117 CR_CALL(fid_parse_arglist, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22118 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22119 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22120
Marko Mikulicic 0:c0ecb8bf28eb 22121 /* parse_member {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22122 /* parse_member's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22123 typedef struct fid_parse_member_arg { ast_off_t pos; } fid_parse_member_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22124
Marko Mikulicic 0:c0ecb8bf28eb 22125 /* parse_member's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22126 typedef struct fid_parse_member_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22127 struct fid_parse_member_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22128 } fid_parse_member_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22129
Marko Mikulicic 0:c0ecb8bf28eb 22130 #define CALL_PARSE_MEMBER(_pos, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 22131 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22132 N.fid_parse_member.pos = (_pos); \
Marko Mikulicic 0:c0ecb8bf28eb 22133 CR_CALL(fid_parse_member, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22134 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22135 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22136
Marko Mikulicic 0:c0ecb8bf28eb 22137 /* parse_memberexpr {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22138 /* parse_memberexpr's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22139 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22140 typedef struct fid_parse_memberexpr_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22141 } fid_parse_memberexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22142 #else
Marko Mikulicic 0:c0ecb8bf28eb 22143 typedef cr_zero_size_type_t fid_parse_memberexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22144 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22145
Marko Mikulicic 0:c0ecb8bf28eb 22146 /* parse_memberexpr's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22147 typedef struct fid_parse_memberexpr_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22148 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22149 struct fid_parse_memberexpr_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22150 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22151
Marko Mikulicic 0:c0ecb8bf28eb 22152 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 22153 } fid_parse_memberexpr_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22154
Marko Mikulicic 0:c0ecb8bf28eb 22155 #define CALL_PARSE_MEMBEREXPR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22156 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22157 CR_CALL(fid_parse_memberexpr, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22158 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22159 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22160
Marko Mikulicic 0:c0ecb8bf28eb 22161 /* parse_var {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22162 /* parse_var's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22163 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22164 typedef struct fid_parse_var_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22165 } fid_parse_var_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22166 #else
Marko Mikulicic 0:c0ecb8bf28eb 22167 typedef cr_zero_size_type_t fid_parse_var_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22168 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22169
Marko Mikulicic 0:c0ecb8bf28eb 22170 /* parse_var's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22171 typedef struct fid_parse_var_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22172 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22173 struct fid_parse_var_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22174 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22175
Marko Mikulicic 0:c0ecb8bf28eb 22176 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22177 } fid_parse_var_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22178
Marko Mikulicic 0:c0ecb8bf28eb 22179 #define CALL_PARSE_VAR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22180 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22181 CR_CALL(fid_parse_var, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22182 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22183 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22184
Marko Mikulicic 0:c0ecb8bf28eb 22185 /* parse_prop {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22186 /* parse_prop's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22187 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22188 typedef struct fid_parse_prop_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22189 } fid_parse_prop_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22190 #else
Marko Mikulicic 0:c0ecb8bf28eb 22191 typedef cr_zero_size_type_t fid_parse_prop_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22192 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22193
Marko Mikulicic 0:c0ecb8bf28eb 22194 /* parse_prop's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22195 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22196 typedef struct fid_parse_prop_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22197 struct fid_parse_prop_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22198 } fid_parse_prop_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22199 #else
Marko Mikulicic 0:c0ecb8bf28eb 22200 typedef cr_zero_size_type_t fid_parse_prop_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22201 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22202
Marko Mikulicic 0:c0ecb8bf28eb 22203 #define CALL_PARSE_PROP(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22204 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22205 CR_CALL(fid_parse_prop, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22206 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22207 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22208
Marko Mikulicic 0:c0ecb8bf28eb 22209 /* parse_dowhile {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22210 /* parse_dowhile's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22211 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22212 typedef struct fid_parse_dowhile_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22213 } fid_parse_dowhile_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22214 #else
Marko Mikulicic 0:c0ecb8bf28eb 22215 typedef cr_zero_size_type_t fid_parse_dowhile_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22216 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22217
Marko Mikulicic 0:c0ecb8bf28eb 22218 /* parse_dowhile's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22219 typedef struct fid_parse_dowhile_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22220 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22221 struct fid_parse_dowhile_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22222 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22223
Marko Mikulicic 0:c0ecb8bf28eb 22224 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22225 uint8_t saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 22226 } fid_parse_dowhile_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22227
Marko Mikulicic 0:c0ecb8bf28eb 22228 #define CALL_PARSE_DOWHILE(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22229 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22230 CR_CALL(fid_parse_dowhile, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22231 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22232 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22233
Marko Mikulicic 0:c0ecb8bf28eb 22234 /* parse_for {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22235 /* parse_for's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22236 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22237 typedef struct fid_parse_for_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22238 } fid_parse_for_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22239 #else
Marko Mikulicic 0:c0ecb8bf28eb 22240 typedef cr_zero_size_type_t fid_parse_for_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22241 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22242
Marko Mikulicic 0:c0ecb8bf28eb 22243 /* parse_for's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22244 typedef struct fid_parse_for_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22245 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22246 struct fid_parse_for_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22247 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22248
Marko Mikulicic 0:c0ecb8bf28eb 22249 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22250 uint8_t saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 22251 } fid_parse_for_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22252
Marko Mikulicic 0:c0ecb8bf28eb 22253 #define CALL_PARSE_FOR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22254 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22255 CR_CALL(fid_parse_for, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22256 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22257 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22258
Marko Mikulicic 0:c0ecb8bf28eb 22259 /* parse_try {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22260 /* parse_try's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22261 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22262 typedef struct fid_parse_try_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22263 } fid_parse_try_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22264 #else
Marko Mikulicic 0:c0ecb8bf28eb 22265 typedef cr_zero_size_type_t fid_parse_try_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22266 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22267
Marko Mikulicic 0:c0ecb8bf28eb 22268 /* parse_try's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22269 typedef struct fid_parse_try_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22270 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22271 struct fid_parse_try_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22272 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22273
Marko Mikulicic 0:c0ecb8bf28eb 22274 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22275 uint8_t catch_or_finally;
Marko Mikulicic 0:c0ecb8bf28eb 22276 } fid_parse_try_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22277
Marko Mikulicic 0:c0ecb8bf28eb 22278 #define CALL_PARSE_TRY(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22279 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22280 CR_CALL(fid_parse_try, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22281 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22282 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22283
Marko Mikulicic 0:c0ecb8bf28eb 22284 /* parse_switch {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22285 /* parse_switch's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22286 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22287 typedef struct fid_parse_switch_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22288 } fid_parse_switch_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22289 #else
Marko Mikulicic 0:c0ecb8bf28eb 22290 typedef cr_zero_size_type_t fid_parse_switch_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22291 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22292
Marko Mikulicic 0:c0ecb8bf28eb 22293 /* parse_switch's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22294 typedef struct fid_parse_switch_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22295 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22296 struct fid_parse_switch_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22297 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22298
Marko Mikulicic 0:c0ecb8bf28eb 22299 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22300 int saved_in_switch;
Marko Mikulicic 0:c0ecb8bf28eb 22301 ast_off_t case_start;
Marko Mikulicic 0:c0ecb8bf28eb 22302 } fid_parse_switch_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22303
Marko Mikulicic 0:c0ecb8bf28eb 22304 #define CALL_PARSE_SWITCH(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22305 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22306 CR_CALL(fid_parse_switch, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22307 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22308 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22309
Marko Mikulicic 0:c0ecb8bf28eb 22310 /* parse_with {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22311 /* parse_with's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22312 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22313 typedef struct fid_parse_with_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22314 } fid_parse_with_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22315 #else
Marko Mikulicic 0:c0ecb8bf28eb 22316 typedef cr_zero_size_type_t fid_parse_with_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22317 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22318
Marko Mikulicic 0:c0ecb8bf28eb 22319 /* parse_with's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22320 typedef struct fid_parse_with_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22321 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22322 struct fid_parse_with_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22323 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22324
Marko Mikulicic 0:c0ecb8bf28eb 22325 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22326 } fid_parse_with_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22327
Marko Mikulicic 0:c0ecb8bf28eb 22328 #define CALL_PARSE_WITH(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22329 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22330 CR_CALL(fid_parse_with, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22331 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22332 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22333
Marko Mikulicic 0:c0ecb8bf28eb 22334 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22335
Marko Mikulicic 0:c0ecb8bf28eb 22336 /*
Marko Mikulicic 0:c0ecb8bf28eb 22337 * Array of "function" descriptors. Each descriptor contains just a size
Marko Mikulicic 0:c0ecb8bf28eb 22338 * of "function"'s locals.
Marko Mikulicic 0:c0ecb8bf28eb 22339 */
Marko Mikulicic 0:c0ecb8bf28eb 22340 static const struct cr_func_desc _fid_descrs[MY_FID_CNT] = {
Marko Mikulicic 0:c0ecb8bf28eb 22341
Marko Mikulicic 0:c0ecb8bf28eb 22342 /* fid_none */
Marko Mikulicic 0:c0ecb8bf28eb 22343 {0},
Marko Mikulicic 0:c0ecb8bf28eb 22344
Marko Mikulicic 0:c0ecb8bf28eb 22345 /* fid_parse_script ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22346 /* fid_parse_script */
Marko Mikulicic 0:c0ecb8bf28eb 22347 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22348 /* fid_p_script_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22349 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22350 /* fid_p_script_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22351 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22352 /* fid_p_script_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22353 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22354 /* fid_p_script_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22355 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22356
Marko Mikulicic 0:c0ecb8bf28eb 22357 /* fid_parse_use_strict ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22358 /* fid_parse_use_strict */
Marko Mikulicic 0:c0ecb8bf28eb 22359 {CR_LOCALS_SIZEOF(fid_parse_use_strict_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22360
Marko Mikulicic 0:c0ecb8bf28eb 22361 /* fid_parse_body ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22362 /* fid_parse_body */
Marko Mikulicic 0:c0ecb8bf28eb 22363 {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22364 /* fid_p_body_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22365 {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22366 /* fid_p_body_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22367 {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22368
Marko Mikulicic 0:c0ecb8bf28eb 22369 /* fid_parse_statement ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22370 /* fid_parse_statement */
Marko Mikulicic 0:c0ecb8bf28eb 22371 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22372 /* fid_p_stat_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22373 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22374 /* fid_p_stat_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22375 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22376 /* fid_p_stat_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22377 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22378 /* fid_p_stat_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22379 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22380 /* fid_p_stat_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22381 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22382 /* fid_p_stat_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22383 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22384 /* fid_p_stat_7 */
Marko Mikulicic 0:c0ecb8bf28eb 22385 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22386 /* fid_p_stat_8 */
Marko Mikulicic 0:c0ecb8bf28eb 22387 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22388 /* fid_p_stat_9 */
Marko Mikulicic 0:c0ecb8bf28eb 22389 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22390 /* fid_p_stat_10 */
Marko Mikulicic 0:c0ecb8bf28eb 22391 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22392 /* fid_p_stat_11 */
Marko Mikulicic 0:c0ecb8bf28eb 22393 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22394 /* fid_p_stat_12 */
Marko Mikulicic 0:c0ecb8bf28eb 22395 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22396 /* fid_p_stat_13 */
Marko Mikulicic 0:c0ecb8bf28eb 22397 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22398 /* fid_p_stat_14 */
Marko Mikulicic 0:c0ecb8bf28eb 22399 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22400
Marko Mikulicic 0:c0ecb8bf28eb 22401 /* fid_parse_expression ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22402 /* fid_parse_expression */
Marko Mikulicic 0:c0ecb8bf28eb 22403 {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22404 /* fid_p_expr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22405 {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22406
Marko Mikulicic 0:c0ecb8bf28eb 22407 /* fid_parse_assign ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22408 /* fid_parse_assign */
Marko Mikulicic 0:c0ecb8bf28eb 22409 {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22410 /* fid_p_assign_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22411 {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22412
Marko Mikulicic 0:c0ecb8bf28eb 22413 /* fid_parse_binary ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22414 /* fid_parse_binary */
Marko Mikulicic 0:c0ecb8bf28eb 22415 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22416 /* fid_p_binary_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22417 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22418 /* fid_p_binary_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22419 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22420 /* fid_p_binary_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22421 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22422 /* fid_p_binary_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22423 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22424 /* fid_p_binary_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22425 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22426 /* fid_p_binary_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22427 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22428
Marko Mikulicic 0:c0ecb8bf28eb 22429 /* fid_parse_prefix ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22430 /* fid_parse_prefix */
Marko Mikulicic 0:c0ecb8bf28eb 22431 {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22432 /* fid_p_prefix_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22433 {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22434
Marko Mikulicic 0:c0ecb8bf28eb 22435 /* fid_parse_postfix ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22436 /* fid_parse_postfix */
Marko Mikulicic 0:c0ecb8bf28eb 22437 {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22438 /* fid_p_postfix_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22439 {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22440
Marko Mikulicic 0:c0ecb8bf28eb 22441 /* fid_parse_callexpr ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22442 /* fid_parse_callexpr */
Marko Mikulicic 0:c0ecb8bf28eb 22443 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22444 /* fid_p_callexpr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22445 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22446 /* fid_p_callexpr_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22447 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22448 /* fid_p_callexpr_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22449 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22450
Marko Mikulicic 0:c0ecb8bf28eb 22451 /* fid_parse_newexpr ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22452 /* fid_parse_newexpr */
Marko Mikulicic 0:c0ecb8bf28eb 22453 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22454 /* fid_p_newexpr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22455 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22456 /* fid_p_newexpr_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22457 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22458 /* fid_p_newexpr_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22459 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22460 /* fid_p_newexpr_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22461 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22462
Marko Mikulicic 0:c0ecb8bf28eb 22463 /* fid_parse_terminal ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22464 /* fid_parse_terminal */
Marko Mikulicic 0:c0ecb8bf28eb 22465 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22466 /* fid_p_terminal_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22467 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22468 /* fid_p_terminal_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22469 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22470 /* fid_p_terminal_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22471 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22472 /* fid_p_terminal_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22473 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22474
Marko Mikulicic 0:c0ecb8bf28eb 22475 /* fid_parse_block ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22476 /* fid_parse_block */
Marko Mikulicic 0:c0ecb8bf28eb 22477 {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22478 /* fid_p_block_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22479 {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22480
Marko Mikulicic 0:c0ecb8bf28eb 22481 /* fid_parse_if ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22482 /* fid_parse_if */
Marko Mikulicic 0:c0ecb8bf28eb 22483 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22484 /* fid_p_if_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22485 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22486 /* fid_p_if_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22487 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22488 /* fid_p_if_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22489 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22490
Marko Mikulicic 0:c0ecb8bf28eb 22491 /* fid_parse_while ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22492 /* fid_parse_while */
Marko Mikulicic 0:c0ecb8bf28eb 22493 {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22494 /* fid_p_while_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22495 {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22496 /* fid_p_while_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22497 {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22498
Marko Mikulicic 0:c0ecb8bf28eb 22499 /* fid_parse_ident ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22500 /* fid_parse_ident */
Marko Mikulicic 0:c0ecb8bf28eb 22501 {CR_LOCALS_SIZEOF(fid_parse_ident_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22502
Marko Mikulicic 0:c0ecb8bf28eb 22503 /* fid_parse_ident_allow_reserved_words -------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22504 /* fid_parse_ident_allow_reserved_words */
Marko Mikulicic 0:c0ecb8bf28eb 22505 {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22506 /* fid_p_ident_allow_reserved_words_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22507 {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22508
Marko Mikulicic 0:c0ecb8bf28eb 22509 /* fid_parse_funcdecl ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22510 /* fid_parse_funcdecl */
Marko Mikulicic 0:c0ecb8bf28eb 22511 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22512 /* fid_p_funcdecl_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22513 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22514 /* fid_p_funcdecl_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22515 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22516 /* fid_p_funcdecl_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22517 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22518 /* fid_p_funcdecl_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22519 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22520 /* fid_p_funcdecl_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22521 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22522 /* fid_p_funcdecl_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22523 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22524 /* fid_p_funcdecl_7 */
Marko Mikulicic 0:c0ecb8bf28eb 22525 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22526 /* fid_p_funcdecl_8 */
Marko Mikulicic 0:c0ecb8bf28eb 22527 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22528 /* fid_p_funcdecl_9 */
Marko Mikulicic 0:c0ecb8bf28eb 22529 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22530
Marko Mikulicic 0:c0ecb8bf28eb 22531 /* fid_parse_arglist ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22532 /* fid_parse_arglist */
Marko Mikulicic 0:c0ecb8bf28eb 22533 {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22534 /* fid_p_arglist_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22535 {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22536
Marko Mikulicic 0:c0ecb8bf28eb 22537 /* fid_parse_member ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22538 /* fid_parse_member */
Marko Mikulicic 0:c0ecb8bf28eb 22539 {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22540 /* fid_p_member_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22541 {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22542
Marko Mikulicic 0:c0ecb8bf28eb 22543 /* fid_parse_memberexpr ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22544 /* fid_parse_memberexpr */
Marko Mikulicic 0:c0ecb8bf28eb 22545 {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22546 /* fid_p_memberexpr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22547 {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22548 /* fid_p_memberexpr_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22549 {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22550
Marko Mikulicic 0:c0ecb8bf28eb 22551 /* fid_parse_var ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22552 /* fid_parse_var */
Marko Mikulicic 0:c0ecb8bf28eb 22553 {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22554 /* fid_p_var_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22555 {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22556
Marko Mikulicic 0:c0ecb8bf28eb 22557 /* fid_parse_prop ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22558 /* fid_parse_prop */
Marko Mikulicic 0:c0ecb8bf28eb 22559 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22560 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22561 /* fid_p_prop_1_getter */
Marko Mikulicic 0:c0ecb8bf28eb 22562 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22563 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22564 /* fid_p_prop_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22565 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22566 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22567 /* fid_p_prop_3_setter */
Marko Mikulicic 0:c0ecb8bf28eb 22568 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22569 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22570 /* fid_p_prop_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22571 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22572
Marko Mikulicic 0:c0ecb8bf28eb 22573 /* fid_parse_dowhile ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22574 /* fid_parse_dowhile */
Marko Mikulicic 0:c0ecb8bf28eb 22575 {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22576 /* fid_p_dowhile_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22577 {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22578 /* fid_p_dowhile_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22579 {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22580
Marko Mikulicic 0:c0ecb8bf28eb 22581 /* fid_parse_for ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22582 /* fid_parse_for */
Marko Mikulicic 0:c0ecb8bf28eb 22583 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22584 /* fid_p_for_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22585 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22586 /* fid_p_for_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22587 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22588 /* fid_p_for_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22589 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22590 /* fid_p_for_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22591 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22592 /* fid_p_for_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22593 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22594 /* fid_p_for_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22595 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22596
Marko Mikulicic 0:c0ecb8bf28eb 22597 /* fid_parse_try ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22598 /* fid_parse_try */
Marko Mikulicic 0:c0ecb8bf28eb 22599 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22600 /* fid_p_try_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22601 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22602 /* fid_p_try_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22603 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22604 /* fid_p_try_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22605 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22606 /* fid_p_try_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22607 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22608
Marko Mikulicic 0:c0ecb8bf28eb 22609 /* fid_parse_switch ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22610 /* fid_parse_switch */
Marko Mikulicic 0:c0ecb8bf28eb 22611 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22612 /* fid_p_switch_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22613 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22614 /* fid_p_switch_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22615 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22616 /* fid_p_switch_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22617 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22618 /* fid_p_switch_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22619 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22620
Marko Mikulicic 0:c0ecb8bf28eb 22621 /* fid_parse_with ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22622 /* fid_parse_with */
Marko Mikulicic 0:c0ecb8bf28eb 22623 {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22624 /* fid_p_with_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22625 {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22626 /* fid_p_with_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22627 {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22628
Marko Mikulicic 0:c0ecb8bf28eb 22629 };
Marko Mikulicic 0:c0ecb8bf28eb 22630
Marko Mikulicic 0:c0ecb8bf28eb 22631 /*
Marko Mikulicic 0:c0ecb8bf28eb 22632 * Union of arguments and return values for all existing "functions".
Marko Mikulicic 0:c0ecb8bf28eb 22633 *
Marko Mikulicic 0:c0ecb8bf28eb 22634 * Used as an accumulator when we call function, return from function,
Marko Mikulicic 0:c0ecb8bf28eb 22635 * yield, or resume.
Marko Mikulicic 0:c0ecb8bf28eb 22636 */
Marko Mikulicic 0:c0ecb8bf28eb 22637 union user_arg_ret {
Marko Mikulicic 0:c0ecb8bf28eb 22638 /* arguments to the next function */
Marko Mikulicic 0:c0ecb8bf28eb 22639 union {
Marko Mikulicic 0:c0ecb8bf28eb 22640 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22641 fid_parse_script_arg_t fid_parse_script;
Marko Mikulicic 0:c0ecb8bf28eb 22642 fid_parse_use_strict_arg_t fid_parse_use_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22643 fid_parse_statement_arg_t fid_parse_statement;
Marko Mikulicic 0:c0ecb8bf28eb 22644 fid_parse_expression_arg_t fid_parse_expression;
Marko Mikulicic 0:c0ecb8bf28eb 22645 fid_parse_assign_arg_t fid_parse_assign;
Marko Mikulicic 0:c0ecb8bf28eb 22646 fid_parse_prefix_arg_t fid_parse_prefix;
Marko Mikulicic 0:c0ecb8bf28eb 22647 fid_parse_postfix_arg_t fid_parse_postfix;
Marko Mikulicic 0:c0ecb8bf28eb 22648 fid_parse_callexpr_arg_t fid_parse_callexpr;
Marko Mikulicic 0:c0ecb8bf28eb 22649 fid_parse_newexpr_arg_t fid_parse_newexpr;
Marko Mikulicic 0:c0ecb8bf28eb 22650 fid_parse_terminal_arg_t fid_parse_terminal;
Marko Mikulicic 0:c0ecb8bf28eb 22651 fid_parse_block_arg_t fid_parse_block;
Marko Mikulicic 0:c0ecb8bf28eb 22652 fid_parse_if_arg_t fid_parse_if;
Marko Mikulicic 0:c0ecb8bf28eb 22653 fid_parse_while_arg_t fid_parse_while;
Marko Mikulicic 0:c0ecb8bf28eb 22654 fid_parse_ident_arg_t fid_parse_ident;
Marko Mikulicic 0:c0ecb8bf28eb 22655 fid_parse_ident_allow_reserved_words_arg_t
Marko Mikulicic 0:c0ecb8bf28eb 22656 fid_parse_ident_allow_reserved_words;
Marko Mikulicic 0:c0ecb8bf28eb 22657 fid_parse_arglist_arg_t fid_parse_arglist;
Marko Mikulicic 0:c0ecb8bf28eb 22658 fid_parse_memberexpr_arg_t fid_parse_memberexpr;
Marko Mikulicic 0:c0ecb8bf28eb 22659 fid_parse_var_arg_t fid_parse_var;
Marko Mikulicic 0:c0ecb8bf28eb 22660 fid_parse_prop_arg_t fid_parse_prop;
Marko Mikulicic 0:c0ecb8bf28eb 22661 fid_parse_dowhile_arg_t fid_parse_dowhile;
Marko Mikulicic 0:c0ecb8bf28eb 22662 fid_parse_for_arg_t fid_parse_for;
Marko Mikulicic 0:c0ecb8bf28eb 22663 fid_parse_try_arg_t fid_parse_try;
Marko Mikulicic 0:c0ecb8bf28eb 22664 fid_parse_switch_arg_t fid_parse_switch;
Marko Mikulicic 0:c0ecb8bf28eb 22665 fid_parse_with_arg_t fid_parse_with;
Marko Mikulicic 0:c0ecb8bf28eb 22666 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22667 fid_parse_body_arg_t fid_parse_body;
Marko Mikulicic 0:c0ecb8bf28eb 22668 fid_parse_binary_arg_t fid_parse_binary;
Marko Mikulicic 0:c0ecb8bf28eb 22669 fid_parse_funcdecl_arg_t fid_parse_funcdecl;
Marko Mikulicic 0:c0ecb8bf28eb 22670 fid_parse_member_arg_t fid_parse_member;
Marko Mikulicic 0:c0ecb8bf28eb 22671 } arg;
Marko Mikulicic 0:c0ecb8bf28eb 22672
Marko Mikulicic 0:c0ecb8bf28eb 22673 /* value returned from function */
Marko Mikulicic 0:c0ecb8bf28eb 22674 /*
Marko Mikulicic 0:c0ecb8bf28eb 22675 union {
Marko Mikulicic 0:c0ecb8bf28eb 22676 } ret;
Marko Mikulicic 0:c0ecb8bf28eb 22677 */
Marko Mikulicic 0:c0ecb8bf28eb 22678 };
Marko Mikulicic 0:c0ecb8bf28eb 22679
Marko Mikulicic 0:c0ecb8bf28eb 22680 static enum v7_tok next_tok(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 22681 int prev_line_no = v7->pstate.prev_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22682 v7->pstate.prev_line_no = v7->pstate.line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22683 v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end);
Marko Mikulicic 0:c0ecb8bf28eb 22684 v7->after_newline = prev_line_no != v7->pstate.line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22685 v7->tok = v7->pstate.pc;
Marko Mikulicic 0:c0ecb8bf28eb 22686 v7->cur_tok = get_tok(&v7->pstate.pc, v7->pstate.src_end, &v7->cur_tok_dbl,
Marko Mikulicic 0:c0ecb8bf28eb 22687 v7->cur_tok);
Marko Mikulicic 0:c0ecb8bf28eb 22688 v7->tok_len = v7->pstate.pc - v7->tok;
Marko Mikulicic 0:c0ecb8bf28eb 22689 v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end);
Marko Mikulicic 0:c0ecb8bf28eb 22690 return v7->cur_tok;
Marko Mikulicic 0:c0ecb8bf28eb 22691 }
Marko Mikulicic 0:c0ecb8bf28eb 22692
Marko Mikulicic 0:c0ecb8bf28eb 22693 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 22694 /*
Marko Mikulicic 0:c0ecb8bf28eb 22695 * Assumes `offset` points to the byte right after a tag
Marko Mikulicic 0:c0ecb8bf28eb 22696 */
Marko Mikulicic 0:c0ecb8bf28eb 22697 static void insert_line_no_if_changed(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22698 ast_off_t offset) {
Marko Mikulicic 0:c0ecb8bf28eb 22699 if (v7->pstate.prev_line_no != v7->line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 22700 v7->line_no = v7->pstate.prev_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22701 ast_add_line_no(a, offset - 1, v7->line_no);
Marko Mikulicic 0:c0ecb8bf28eb 22702 } else {
Marko Mikulicic 0:c0ecb8bf28eb 22703 #if V7_AST_FORCE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 22704 /*
Marko Mikulicic 0:c0ecb8bf28eb 22705 * This mode is needed for debug only: to make sure AST consumers correctly
Marko Mikulicic 0:c0ecb8bf28eb 22706 * consume all nodes with line numbers data encoded
Marko Mikulicic 0:c0ecb8bf28eb 22707 */
Marko Mikulicic 0:c0ecb8bf28eb 22708 ast_add_line_no(a, offset - 1, 0);
Marko Mikulicic 0:c0ecb8bf28eb 22709 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22710 }
Marko Mikulicic 0:c0ecb8bf28eb 22711 }
Marko Mikulicic 0:c0ecb8bf28eb 22712 #else
Marko Mikulicic 0:c0ecb8bf28eb 22713 static void insert_line_no_if_changed(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22714 ast_off_t offset) {
Marko Mikulicic 0:c0ecb8bf28eb 22715 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 22716 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 22717 (void) offset;
Marko Mikulicic 0:c0ecb8bf28eb 22718 }
Marko Mikulicic 0:c0ecb8bf28eb 22719 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22720
Marko Mikulicic 0:c0ecb8bf28eb 22721 static ast_off_t insert_node(struct v7 *v7, struct ast *a, ast_off_t start,
Marko Mikulicic 0:c0ecb8bf28eb 22722 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 22723 ast_off_t ret = ast_insert_node(a, start, tag);
Marko Mikulicic 0:c0ecb8bf28eb 22724 insert_line_no_if_changed(v7, a, ret);
Marko Mikulicic 0:c0ecb8bf28eb 22725 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 22726 }
Marko Mikulicic 0:c0ecb8bf28eb 22727
Marko Mikulicic 0:c0ecb8bf28eb 22728 static ast_off_t add_node(struct v7 *v7, struct ast *a, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 22729 return insert_node(v7, a, a->mbuf.len, tag);
Marko Mikulicic 0:c0ecb8bf28eb 22730 }
Marko Mikulicic 0:c0ecb8bf28eb 22731
Marko Mikulicic 0:c0ecb8bf28eb 22732 static ast_off_t insert_inlined_node(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22733 ast_off_t start, enum ast_tag tag,
Marko Mikulicic 0:c0ecb8bf28eb 22734 const char *name, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 22735 ast_off_t ret = ast_insert_inlined_node(a, start, tag, name, len);
Marko Mikulicic 0:c0ecb8bf28eb 22736 insert_line_no_if_changed(v7, a, ret);
Marko Mikulicic 0:c0ecb8bf28eb 22737 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 22738 }
Marko Mikulicic 0:c0ecb8bf28eb 22739
Marko Mikulicic 0:c0ecb8bf28eb 22740 static ast_off_t add_inlined_node(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22741 enum ast_tag tag, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 22742 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 22743 return insert_inlined_node(v7, a, a->mbuf.len, tag, name, len);
Marko Mikulicic 0:c0ecb8bf28eb 22744 }
Marko Mikulicic 0:c0ecb8bf28eb 22745
Marko Mikulicic 0:c0ecb8bf28eb 22746 static unsigned long get_column(const char *code, const char *pos) {
Marko Mikulicic 0:c0ecb8bf28eb 22747 const char *p = pos;
Marko Mikulicic 0:c0ecb8bf28eb 22748 while (p > code && *p != '\n') {
Marko Mikulicic 0:c0ecb8bf28eb 22749 p--;
Marko Mikulicic 0:c0ecb8bf28eb 22750 }
Marko Mikulicic 0:c0ecb8bf28eb 22751 return p == code ? pos - p : pos - (p + 1);
Marko Mikulicic 0:c0ecb8bf28eb 22752 }
Marko Mikulicic 0:c0ecb8bf28eb 22753
Marko Mikulicic 0:c0ecb8bf28eb 22754 static enum v7_err end_of_statement(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 22755 if (v7->cur_tok == TOK_SEMICOLON || v7->cur_tok == TOK_END_OF_INPUT ||
Marko Mikulicic 0:c0ecb8bf28eb 22756 v7->cur_tok == TOK_CLOSE_CURLY || v7->after_newline) {
Marko Mikulicic 0:c0ecb8bf28eb 22757 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 22758 }
Marko Mikulicic 0:c0ecb8bf28eb 22759 return V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 22760 }
Marko Mikulicic 0:c0ecb8bf28eb 22761
Marko Mikulicic 0:c0ecb8bf28eb 22762 static enum v7_tok lookahead(const struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 22763 const char *s = v7->pstate.pc;
Marko Mikulicic 0:c0ecb8bf28eb 22764 double d;
Marko Mikulicic 0:c0ecb8bf28eb 22765 return get_tok(&s, v7->pstate.src_end, &d, v7->cur_tok);
Marko Mikulicic 0:c0ecb8bf28eb 22766 }
Marko Mikulicic 0:c0ecb8bf28eb 22767
Marko Mikulicic 0:c0ecb8bf28eb 22768 static int parse_optional(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22769 enum v7_tok terminator) {
Marko Mikulicic 0:c0ecb8bf28eb 22770 if (v7->cur_tok != terminator) {
Marko Mikulicic 0:c0ecb8bf28eb 22771 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 22772 }
Marko Mikulicic 0:c0ecb8bf28eb 22773 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 22774 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 22775 }
Marko Mikulicic 0:c0ecb8bf28eb 22776
Marko Mikulicic 0:c0ecb8bf28eb 22777 /*
Marko Mikulicic 0:c0ecb8bf28eb 22778 * On ESP8266 'levels' declaration have to be outside of 'parse_binary'
Marko Mikulicic 0:c0ecb8bf28eb 22779 * in order to prevent reboot on return from this function
Marko Mikulicic 0:c0ecb8bf28eb 22780 * TODO(alashkin): understand why
Marko Mikulicic 0:c0ecb8bf28eb 22781 */
Marko Mikulicic 0:c0ecb8bf28eb 22782 #define NONE \
Marko Mikulicic 0:c0ecb8bf28eb 22783 { (enum v7_tok) 0, (enum v7_tok) 0, (enum ast_tag) 0 }
Marko Mikulicic 0:c0ecb8bf28eb 22784
Marko Mikulicic 0:c0ecb8bf28eb 22785 static const struct {
Marko Mikulicic 0:c0ecb8bf28eb 22786 int len, left_to_right;
Marko Mikulicic 0:c0ecb8bf28eb 22787 struct {
Marko Mikulicic 0:c0ecb8bf28eb 22788 enum v7_tok start_tok, end_tok;
Marko Mikulicic 0:c0ecb8bf28eb 22789 enum ast_tag start_ast;
Marko Mikulicic 0:c0ecb8bf28eb 22790 } parts[2];
Marko Mikulicic 0:c0ecb8bf28eb 22791 } levels[] = {
Marko Mikulicic 0:c0ecb8bf28eb 22792 {1, 0, {{TOK_ASSIGN, TOK_URSHIFT_ASSIGN, AST_ASSIGN}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22793 {1, 0, {{TOK_QUESTION, TOK_QUESTION, AST_COND}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22794 {1, 1, {{TOK_LOGICAL_OR, TOK_LOGICAL_OR, AST_LOGICAL_OR}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22795 {1, 1, {{TOK_LOGICAL_AND, TOK_LOGICAL_AND, AST_LOGICAL_AND}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22796 {1, 1, {{TOK_OR, TOK_OR, AST_OR}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22797 {1, 1, {{TOK_XOR, TOK_XOR, AST_XOR}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22798 {1, 1, {{TOK_AND, TOK_AND, AST_AND}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22799 {1, 1, {{TOK_EQ, TOK_NE_NE, AST_EQ}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22800 {2, 1, {{TOK_LE, TOK_GT, AST_LE}, {TOK_IN, TOK_INSTANCEOF, AST_IN}}},
Marko Mikulicic 0:c0ecb8bf28eb 22801 {1, 1, {{TOK_LSHIFT, TOK_URSHIFT, AST_LSHIFT}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22802 {1, 1, {{TOK_PLUS, TOK_MINUS, AST_ADD}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22803 {1, 1, {{TOK_REM, TOK_DIV, AST_REM}, NONE}}};
Marko Mikulicic 0:c0ecb8bf28eb 22804
Marko Mikulicic 0:c0ecb8bf28eb 22805 enum cr_status parser_cr_exec(struct cr_ctx *p_ctx, struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 22806 struct ast *a) {
Marko Mikulicic 0:c0ecb8bf28eb 22807 enum cr_status rc = CR_RES__OK;
Marko Mikulicic 0:c0ecb8bf28eb 22808
Marko Mikulicic 0:c0ecb8bf28eb 22809 _cr_iter_begin:
Marko Mikulicic 0:c0ecb8bf28eb 22810
Marko Mikulicic 0:c0ecb8bf28eb 22811 rc = cr_on_iter_begin(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 22812 if (rc != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 22813 return rc;
Marko Mikulicic 0:c0ecb8bf28eb 22814 }
Marko Mikulicic 0:c0ecb8bf28eb 22815
Marko Mikulicic 0:c0ecb8bf28eb 22816 /*
Marko Mikulicic 0:c0ecb8bf28eb 22817 * dispatcher switch: depending on the fid, jump to the corresponding label
Marko Mikulicic 0:c0ecb8bf28eb 22818 */
Marko Mikulicic 0:c0ecb8bf28eb 22819 switch ((enum my_fid) CR_CURR_FUNC()) {
Marko Mikulicic 0:c0ecb8bf28eb 22820 CR_DEFINE_ENTRY_POINT(fid_none);
Marko Mikulicic 0:c0ecb8bf28eb 22821
Marko Mikulicic 0:c0ecb8bf28eb 22822 CR_DEFINE_ENTRY_POINT(fid_parse_script);
Marko Mikulicic 0:c0ecb8bf28eb 22823 CR_DEFINE_ENTRY_POINT(fid_p_script_1);
Marko Mikulicic 0:c0ecb8bf28eb 22824 CR_DEFINE_ENTRY_POINT(fid_p_script_2);
Marko Mikulicic 0:c0ecb8bf28eb 22825 CR_DEFINE_ENTRY_POINT(fid_p_script_3);
Marko Mikulicic 0:c0ecb8bf28eb 22826 CR_DEFINE_ENTRY_POINT(fid_p_script_4);
Marko Mikulicic 0:c0ecb8bf28eb 22827
Marko Mikulicic 0:c0ecb8bf28eb 22828 CR_DEFINE_ENTRY_POINT(fid_parse_use_strict);
Marko Mikulicic 0:c0ecb8bf28eb 22829
Marko Mikulicic 0:c0ecb8bf28eb 22830 CR_DEFINE_ENTRY_POINT(fid_parse_body);
Marko Mikulicic 0:c0ecb8bf28eb 22831 CR_DEFINE_ENTRY_POINT(fid_p_body_1);
Marko Mikulicic 0:c0ecb8bf28eb 22832 CR_DEFINE_ENTRY_POINT(fid_p_body_2);
Marko Mikulicic 0:c0ecb8bf28eb 22833
Marko Mikulicic 0:c0ecb8bf28eb 22834 CR_DEFINE_ENTRY_POINT(fid_parse_statement);
Marko Mikulicic 0:c0ecb8bf28eb 22835 CR_DEFINE_ENTRY_POINT(fid_p_stat_1);
Marko Mikulicic 0:c0ecb8bf28eb 22836 CR_DEFINE_ENTRY_POINT(fid_p_stat_2);
Marko Mikulicic 0:c0ecb8bf28eb 22837 CR_DEFINE_ENTRY_POINT(fid_p_stat_3);
Marko Mikulicic 0:c0ecb8bf28eb 22838 CR_DEFINE_ENTRY_POINT(fid_p_stat_4);
Marko Mikulicic 0:c0ecb8bf28eb 22839 CR_DEFINE_ENTRY_POINT(fid_p_stat_5);
Marko Mikulicic 0:c0ecb8bf28eb 22840 CR_DEFINE_ENTRY_POINT(fid_p_stat_6);
Marko Mikulicic 0:c0ecb8bf28eb 22841 CR_DEFINE_ENTRY_POINT(fid_p_stat_7);
Marko Mikulicic 0:c0ecb8bf28eb 22842 CR_DEFINE_ENTRY_POINT(fid_p_stat_8);
Marko Mikulicic 0:c0ecb8bf28eb 22843 CR_DEFINE_ENTRY_POINT(fid_p_stat_9);
Marko Mikulicic 0:c0ecb8bf28eb 22844 CR_DEFINE_ENTRY_POINT(fid_p_stat_10);
Marko Mikulicic 0:c0ecb8bf28eb 22845 CR_DEFINE_ENTRY_POINT(fid_p_stat_11);
Marko Mikulicic 0:c0ecb8bf28eb 22846 CR_DEFINE_ENTRY_POINT(fid_p_stat_12);
Marko Mikulicic 0:c0ecb8bf28eb 22847 CR_DEFINE_ENTRY_POINT(fid_p_stat_13);
Marko Mikulicic 0:c0ecb8bf28eb 22848 CR_DEFINE_ENTRY_POINT(fid_p_stat_14);
Marko Mikulicic 0:c0ecb8bf28eb 22849
Marko Mikulicic 0:c0ecb8bf28eb 22850 CR_DEFINE_ENTRY_POINT(fid_parse_expression);
Marko Mikulicic 0:c0ecb8bf28eb 22851 CR_DEFINE_ENTRY_POINT(fid_p_expr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22852
Marko Mikulicic 0:c0ecb8bf28eb 22853 CR_DEFINE_ENTRY_POINT(fid_parse_assign);
Marko Mikulicic 0:c0ecb8bf28eb 22854 CR_DEFINE_ENTRY_POINT(fid_p_assign_1);
Marko Mikulicic 0:c0ecb8bf28eb 22855
Marko Mikulicic 0:c0ecb8bf28eb 22856 CR_DEFINE_ENTRY_POINT(fid_parse_binary);
Marko Mikulicic 0:c0ecb8bf28eb 22857 CR_DEFINE_ENTRY_POINT(fid_p_binary_2);
Marko Mikulicic 0:c0ecb8bf28eb 22858 CR_DEFINE_ENTRY_POINT(fid_p_binary_3);
Marko Mikulicic 0:c0ecb8bf28eb 22859 CR_DEFINE_ENTRY_POINT(fid_p_binary_4);
Marko Mikulicic 0:c0ecb8bf28eb 22860 CR_DEFINE_ENTRY_POINT(fid_p_binary_5);
Marko Mikulicic 0:c0ecb8bf28eb 22861 CR_DEFINE_ENTRY_POINT(fid_p_binary_6);
Marko Mikulicic 0:c0ecb8bf28eb 22862
Marko Mikulicic 0:c0ecb8bf28eb 22863 CR_DEFINE_ENTRY_POINT(fid_parse_prefix);
Marko Mikulicic 0:c0ecb8bf28eb 22864 CR_DEFINE_ENTRY_POINT(fid_p_prefix_1);
Marko Mikulicic 0:c0ecb8bf28eb 22865
Marko Mikulicic 0:c0ecb8bf28eb 22866 CR_DEFINE_ENTRY_POINT(fid_parse_postfix);
Marko Mikulicic 0:c0ecb8bf28eb 22867 CR_DEFINE_ENTRY_POINT(fid_p_postfix_1);
Marko Mikulicic 0:c0ecb8bf28eb 22868
Marko Mikulicic 0:c0ecb8bf28eb 22869 CR_DEFINE_ENTRY_POINT(fid_parse_callexpr);
Marko Mikulicic 0:c0ecb8bf28eb 22870 CR_DEFINE_ENTRY_POINT(fid_p_callexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22871 CR_DEFINE_ENTRY_POINT(fid_p_callexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 22872 CR_DEFINE_ENTRY_POINT(fid_p_callexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 22873
Marko Mikulicic 0:c0ecb8bf28eb 22874 CR_DEFINE_ENTRY_POINT(fid_parse_newexpr);
Marko Mikulicic 0:c0ecb8bf28eb 22875 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22876 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 22877 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 22878 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_4);
Marko Mikulicic 0:c0ecb8bf28eb 22879
Marko Mikulicic 0:c0ecb8bf28eb 22880 CR_DEFINE_ENTRY_POINT(fid_parse_terminal);
Marko Mikulicic 0:c0ecb8bf28eb 22881 CR_DEFINE_ENTRY_POINT(fid_p_terminal_1);
Marko Mikulicic 0:c0ecb8bf28eb 22882 CR_DEFINE_ENTRY_POINT(fid_p_terminal_2);
Marko Mikulicic 0:c0ecb8bf28eb 22883 CR_DEFINE_ENTRY_POINT(fid_p_terminal_3);
Marko Mikulicic 0:c0ecb8bf28eb 22884 CR_DEFINE_ENTRY_POINT(fid_p_terminal_4);
Marko Mikulicic 0:c0ecb8bf28eb 22885
Marko Mikulicic 0:c0ecb8bf28eb 22886 CR_DEFINE_ENTRY_POINT(fid_parse_block);
Marko Mikulicic 0:c0ecb8bf28eb 22887 CR_DEFINE_ENTRY_POINT(fid_p_block_1);
Marko Mikulicic 0:c0ecb8bf28eb 22888
Marko Mikulicic 0:c0ecb8bf28eb 22889 CR_DEFINE_ENTRY_POINT(fid_parse_if);
Marko Mikulicic 0:c0ecb8bf28eb 22890 CR_DEFINE_ENTRY_POINT(fid_p_if_1);
Marko Mikulicic 0:c0ecb8bf28eb 22891 CR_DEFINE_ENTRY_POINT(fid_p_if_2);
Marko Mikulicic 0:c0ecb8bf28eb 22892 CR_DEFINE_ENTRY_POINT(fid_p_if_3);
Marko Mikulicic 0:c0ecb8bf28eb 22893
Marko Mikulicic 0:c0ecb8bf28eb 22894 CR_DEFINE_ENTRY_POINT(fid_parse_while);
Marko Mikulicic 0:c0ecb8bf28eb 22895 CR_DEFINE_ENTRY_POINT(fid_p_while_1);
Marko Mikulicic 0:c0ecb8bf28eb 22896 CR_DEFINE_ENTRY_POINT(fid_p_while_2);
Marko Mikulicic 0:c0ecb8bf28eb 22897
Marko Mikulicic 0:c0ecb8bf28eb 22898 CR_DEFINE_ENTRY_POINT(fid_parse_ident);
Marko Mikulicic 0:c0ecb8bf28eb 22899
Marko Mikulicic 0:c0ecb8bf28eb 22900 CR_DEFINE_ENTRY_POINT(fid_parse_ident_allow_reserved_words);
Marko Mikulicic 0:c0ecb8bf28eb 22901 CR_DEFINE_ENTRY_POINT(fid_p_ident_arw_1);
Marko Mikulicic 0:c0ecb8bf28eb 22902
Marko Mikulicic 0:c0ecb8bf28eb 22903 CR_DEFINE_ENTRY_POINT(fid_parse_funcdecl);
Marko Mikulicic 0:c0ecb8bf28eb 22904 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_1);
Marko Mikulicic 0:c0ecb8bf28eb 22905 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_2);
Marko Mikulicic 0:c0ecb8bf28eb 22906 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_3);
Marko Mikulicic 0:c0ecb8bf28eb 22907 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_4);
Marko Mikulicic 0:c0ecb8bf28eb 22908 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_5);
Marko Mikulicic 0:c0ecb8bf28eb 22909 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_6);
Marko Mikulicic 0:c0ecb8bf28eb 22910 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_7);
Marko Mikulicic 0:c0ecb8bf28eb 22911 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_8);
Marko Mikulicic 0:c0ecb8bf28eb 22912 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_9);
Marko Mikulicic 0:c0ecb8bf28eb 22913
Marko Mikulicic 0:c0ecb8bf28eb 22914 CR_DEFINE_ENTRY_POINT(fid_parse_arglist);
Marko Mikulicic 0:c0ecb8bf28eb 22915 CR_DEFINE_ENTRY_POINT(fid_p_arglist_1);
Marko Mikulicic 0:c0ecb8bf28eb 22916
Marko Mikulicic 0:c0ecb8bf28eb 22917 CR_DEFINE_ENTRY_POINT(fid_parse_member);
Marko Mikulicic 0:c0ecb8bf28eb 22918 CR_DEFINE_ENTRY_POINT(fid_p_member_1);
Marko Mikulicic 0:c0ecb8bf28eb 22919
Marko Mikulicic 0:c0ecb8bf28eb 22920 CR_DEFINE_ENTRY_POINT(fid_parse_memberexpr);
Marko Mikulicic 0:c0ecb8bf28eb 22921 CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22922 CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 22923
Marko Mikulicic 0:c0ecb8bf28eb 22924 CR_DEFINE_ENTRY_POINT(fid_parse_var);
Marko Mikulicic 0:c0ecb8bf28eb 22925 CR_DEFINE_ENTRY_POINT(fid_p_var_1);
Marko Mikulicic 0:c0ecb8bf28eb 22926
Marko Mikulicic 0:c0ecb8bf28eb 22927 CR_DEFINE_ENTRY_POINT(fid_parse_prop);
Marko Mikulicic 0:c0ecb8bf28eb 22928 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22929 CR_DEFINE_ENTRY_POINT(fid_p_prop_1_getter);
Marko Mikulicic 0:c0ecb8bf28eb 22930 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22931 CR_DEFINE_ENTRY_POINT(fid_p_prop_2);
Marko Mikulicic 0:c0ecb8bf28eb 22932 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22933 CR_DEFINE_ENTRY_POINT(fid_p_prop_3_setter);
Marko Mikulicic 0:c0ecb8bf28eb 22934 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22935 CR_DEFINE_ENTRY_POINT(fid_p_prop_4);
Marko Mikulicic 0:c0ecb8bf28eb 22936
Marko Mikulicic 0:c0ecb8bf28eb 22937 CR_DEFINE_ENTRY_POINT(fid_parse_dowhile);
Marko Mikulicic 0:c0ecb8bf28eb 22938 CR_DEFINE_ENTRY_POINT(fid_p_dowhile_1);
Marko Mikulicic 0:c0ecb8bf28eb 22939 CR_DEFINE_ENTRY_POINT(fid_p_dowhile_2);
Marko Mikulicic 0:c0ecb8bf28eb 22940
Marko Mikulicic 0:c0ecb8bf28eb 22941 CR_DEFINE_ENTRY_POINT(fid_parse_for);
Marko Mikulicic 0:c0ecb8bf28eb 22942 CR_DEFINE_ENTRY_POINT(fid_p_for_1);
Marko Mikulicic 0:c0ecb8bf28eb 22943 CR_DEFINE_ENTRY_POINT(fid_p_for_2);
Marko Mikulicic 0:c0ecb8bf28eb 22944 CR_DEFINE_ENTRY_POINT(fid_p_for_3);
Marko Mikulicic 0:c0ecb8bf28eb 22945 CR_DEFINE_ENTRY_POINT(fid_p_for_4);
Marko Mikulicic 0:c0ecb8bf28eb 22946 CR_DEFINE_ENTRY_POINT(fid_p_for_5);
Marko Mikulicic 0:c0ecb8bf28eb 22947 CR_DEFINE_ENTRY_POINT(fid_p_for_6);
Marko Mikulicic 0:c0ecb8bf28eb 22948
Marko Mikulicic 0:c0ecb8bf28eb 22949 CR_DEFINE_ENTRY_POINT(fid_parse_try);
Marko Mikulicic 0:c0ecb8bf28eb 22950 CR_DEFINE_ENTRY_POINT(fid_p_try_1);
Marko Mikulicic 0:c0ecb8bf28eb 22951 CR_DEFINE_ENTRY_POINT(fid_p_try_2);
Marko Mikulicic 0:c0ecb8bf28eb 22952 CR_DEFINE_ENTRY_POINT(fid_p_try_3);
Marko Mikulicic 0:c0ecb8bf28eb 22953 CR_DEFINE_ENTRY_POINT(fid_p_try_4);
Marko Mikulicic 0:c0ecb8bf28eb 22954
Marko Mikulicic 0:c0ecb8bf28eb 22955 CR_DEFINE_ENTRY_POINT(fid_parse_switch);
Marko Mikulicic 0:c0ecb8bf28eb 22956 CR_DEFINE_ENTRY_POINT(fid_p_switch_1);
Marko Mikulicic 0:c0ecb8bf28eb 22957 CR_DEFINE_ENTRY_POINT(fid_p_switch_2);
Marko Mikulicic 0:c0ecb8bf28eb 22958 CR_DEFINE_ENTRY_POINT(fid_p_switch_3);
Marko Mikulicic 0:c0ecb8bf28eb 22959 CR_DEFINE_ENTRY_POINT(fid_p_switch_4);
Marko Mikulicic 0:c0ecb8bf28eb 22960
Marko Mikulicic 0:c0ecb8bf28eb 22961 CR_DEFINE_ENTRY_POINT(fid_parse_with);
Marko Mikulicic 0:c0ecb8bf28eb 22962 CR_DEFINE_ENTRY_POINT(fid_p_with_1);
Marko Mikulicic 0:c0ecb8bf28eb 22963 CR_DEFINE_ENTRY_POINT(fid_p_with_2);
Marko Mikulicic 0:c0ecb8bf28eb 22964
Marko Mikulicic 0:c0ecb8bf28eb 22965 default:
Marko Mikulicic 0:c0ecb8bf28eb 22966 /* should never be here */
Marko Mikulicic 0:c0ecb8bf28eb 22967 printf("fatal: wrong func id: %d", CR_CURR_FUNC());
Marko Mikulicic 0:c0ecb8bf28eb 22968 break;
Marko Mikulicic 0:c0ecb8bf28eb 22969 };
Marko Mikulicic 0:c0ecb8bf28eb 22970
Marko Mikulicic 0:c0ecb8bf28eb 22971 /* static enum v7_err parse_script(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 22972 fid_parse_script :
Marko Mikulicic 0:c0ecb8bf28eb 22973 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 22974 #define L CR_CUR_LOCALS_PT(fid_parse_script_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 22975 {
Marko Mikulicic 0:c0ecb8bf28eb 22976 L->start = add_node(v7, a, AST_SCRIPT);
Marko Mikulicic 0:c0ecb8bf28eb 22977 L->outer_last_var_node = v7->last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 22978 L->saved_in_strict = v7->pstate.in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22979
Marko Mikulicic 0:c0ecb8bf28eb 22980 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 22981 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 22982
Marko Mikulicic 0:c0ecb8bf28eb 22983 CR_TRY(fid_p_script_1);
Marko Mikulicic 0:c0ecb8bf28eb 22984 {
Marko Mikulicic 0:c0ecb8bf28eb 22985 CALL_PARSE_USE_STRICT(fid_p_script_3);
Marko Mikulicic 0:c0ecb8bf28eb 22986 v7->pstate.in_strict = 1;
Marko Mikulicic 0:c0ecb8bf28eb 22987 }
Marko Mikulicic 0:c0ecb8bf28eb 22988 CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_script_1, fid_p_script_2);
Marko Mikulicic 0:c0ecb8bf28eb 22989 CR_ENDCATCH(fid_p_script_2);
Marko Mikulicic 0:c0ecb8bf28eb 22990
Marko Mikulicic 0:c0ecb8bf28eb 22991 CALL_PARSE_BODY(TOK_END_OF_INPUT, fid_p_script_4);
Marko Mikulicic 0:c0ecb8bf28eb 22992 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 22993 v7->pstate.in_strict = L->saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22994 v7->last_var_node = L->outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 22995
Marko Mikulicic 0:c0ecb8bf28eb 22996 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 22997 }
Marko Mikulicic 0:c0ecb8bf28eb 22998
Marko Mikulicic 0:c0ecb8bf28eb 22999 /* static enum v7_err parse_use_strict(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23000 fid_parse_use_strict :
Marko Mikulicic 0:c0ecb8bf28eb 23001 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23002 #define L CR_CUR_LOCALS_PT(fid_parse_use_strict_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23003 {
Marko Mikulicic 0:c0ecb8bf28eb 23004 if (v7->cur_tok == TOK_STRING_LITERAL &&
Marko Mikulicic 0:c0ecb8bf28eb 23005 (strncmp(v7->tok, "\"use strict\"", v7->tok_len) == 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 23006 strncmp(v7->tok, "'use strict'", v7->tok_len) == 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 23007 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23008 add_node(v7, a, AST_USE_STRICT);
Marko Mikulicic 0:c0ecb8bf28eb 23009 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23010 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23011 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23012 }
Marko Mikulicic 0:c0ecb8bf28eb 23013 }
Marko Mikulicic 0:c0ecb8bf28eb 23014
Marko Mikulicic 0:c0ecb8bf28eb 23015 /*
Marko Mikulicic 0:c0ecb8bf28eb 23016 * static enum v7_err parse_body(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 23017 * enum v7_tok end)
Marko Mikulicic 0:c0ecb8bf28eb 23018 */
Marko Mikulicic 0:c0ecb8bf28eb 23019 fid_parse_body :
Marko Mikulicic 0:c0ecb8bf28eb 23020 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23021 #define L CR_CUR_LOCALS_PT(fid_parse_body_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23022 {
Marko Mikulicic 0:c0ecb8bf28eb 23023 while (v7->cur_tok != L->arg.end) {
Marko Mikulicic 0:c0ecb8bf28eb 23024 if (ACCEPT(TOK_FUNCTION)) {
Marko Mikulicic 0:c0ecb8bf28eb 23025 if (v7->cur_tok != TOK_IDENTIFIER) {
Marko Mikulicic 0:c0ecb8bf28eb 23026 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23027 }
Marko Mikulicic 0:c0ecb8bf28eb 23028 L->start = add_node(v7, a, AST_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 23029 ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23030 /* zero out var node pointer */
Marko Mikulicic 0:c0ecb8bf28eb 23031 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23032 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 23033 add_inlined_node(v7, a, AST_FUNC_DECL, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23034
Marko Mikulicic 0:c0ecb8bf28eb 23035 CALL_PARSE_FUNCDECL(1, 0, fid_p_body_1);
Marko Mikulicic 0:c0ecb8bf28eb 23036 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23037 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23038 CALL_PARSE_STATEMENT(fid_p_body_2);
Marko Mikulicic 0:c0ecb8bf28eb 23039 }
Marko Mikulicic 0:c0ecb8bf28eb 23040 }
Marko Mikulicic 0:c0ecb8bf28eb 23041 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23042 }
Marko Mikulicic 0:c0ecb8bf28eb 23043
Marko Mikulicic 0:c0ecb8bf28eb 23044 /* static enum v7_err parse_statement(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23045 fid_parse_statement :
Marko Mikulicic 0:c0ecb8bf28eb 23046 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23047 #define L CR_CUR_LOCALS_PT(fid_parse_statement_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23048 {
Marko Mikulicic 0:c0ecb8bf28eb 23049 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23050 case TOK_SEMICOLON:
Marko Mikulicic 0:c0ecb8bf28eb 23051 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23052 /* empty statement */
Marko Mikulicic 0:c0ecb8bf28eb 23053 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23054 case TOK_OPEN_CURLY: /* block */
Marko Mikulicic 0:c0ecb8bf28eb 23055 CALL_PARSE_BLOCK(fid_p_stat_3);
Marko Mikulicic 0:c0ecb8bf28eb 23056 /* returning because no semicolon required */
Marko Mikulicic 0:c0ecb8bf28eb 23057 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23058 case TOK_IF:
Marko Mikulicic 0:c0ecb8bf28eb 23059 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23060 CALL_PARSE_IF(fid_p_stat_4);
Marko Mikulicic 0:c0ecb8bf28eb 23061 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23062 case TOK_WHILE:
Marko Mikulicic 0:c0ecb8bf28eb 23063 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23064 CALL_PARSE_WHILE(fid_p_stat_5);
Marko Mikulicic 0:c0ecb8bf28eb 23065 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23066 case TOK_DO:
Marko Mikulicic 0:c0ecb8bf28eb 23067 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23068 CALL_PARSE_DOWHILE(fid_p_stat_10);
Marko Mikulicic 0:c0ecb8bf28eb 23069 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23070 case TOK_FOR:
Marko Mikulicic 0:c0ecb8bf28eb 23071 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23072 CALL_PARSE_FOR(fid_p_stat_11);
Marko Mikulicic 0:c0ecb8bf28eb 23073 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23074 case TOK_TRY:
Marko Mikulicic 0:c0ecb8bf28eb 23075 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23076 CALL_PARSE_TRY(fid_p_stat_12);
Marko Mikulicic 0:c0ecb8bf28eb 23077 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23078 case TOK_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 23079 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23080 CALL_PARSE_SWITCH(fid_p_stat_13);
Marko Mikulicic 0:c0ecb8bf28eb 23081 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23082 case TOK_WITH:
Marko Mikulicic 0:c0ecb8bf28eb 23083 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23084 CALL_PARSE_WITH(fid_p_stat_14);
Marko Mikulicic 0:c0ecb8bf28eb 23085 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23086 case TOK_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 23087 if (!(v7->pstate.in_loop || v7->pstate.in_switch)) {
Marko Mikulicic 0:c0ecb8bf28eb 23088 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23089 }
Marko Mikulicic 0:c0ecb8bf28eb 23090 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23091 PARSE_WITH_OPT_ARG(AST_BREAK, AST_LABELED_BREAK, CALL_PARSE_IDENT,
Marko Mikulicic 0:c0ecb8bf28eb 23092 fid_p_stat_7);
Marko Mikulicic 0:c0ecb8bf28eb 23093 break;
Marko Mikulicic 0:c0ecb8bf28eb 23094 case TOK_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 23095 if (!v7->pstate.in_loop) {
Marko Mikulicic 0:c0ecb8bf28eb 23096 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23097 }
Marko Mikulicic 0:c0ecb8bf28eb 23098 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23099 PARSE_WITH_OPT_ARG(AST_CONTINUE, AST_LABELED_CONTINUE, CALL_PARSE_IDENT,
Marko Mikulicic 0:c0ecb8bf28eb 23100 fid_p_stat_8);
Marko Mikulicic 0:c0ecb8bf28eb 23101 break;
Marko Mikulicic 0:c0ecb8bf28eb 23102 case TOK_RETURN:
Marko Mikulicic 0:c0ecb8bf28eb 23103 if (!v7->pstate.in_function) {
Marko Mikulicic 0:c0ecb8bf28eb 23104 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23105 }
Marko Mikulicic 0:c0ecb8bf28eb 23106 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23107 PARSE_WITH_OPT_ARG(AST_RETURN, AST_VALUE_RETURN, CALL_PARSE_EXPRESSION,
Marko Mikulicic 0:c0ecb8bf28eb 23108 fid_p_stat_6);
Marko Mikulicic 0:c0ecb8bf28eb 23109 break;
Marko Mikulicic 0:c0ecb8bf28eb 23110 case TOK_THROW:
Marko Mikulicic 0:c0ecb8bf28eb 23111 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23112 add_node(v7, a, AST_THROW);
Marko Mikulicic 0:c0ecb8bf28eb 23113 CALL_PARSE_EXPRESSION(fid_p_stat_2);
Marko Mikulicic 0:c0ecb8bf28eb 23114 break;
Marko Mikulicic 0:c0ecb8bf28eb 23115 case TOK_DEBUGGER:
Marko Mikulicic 0:c0ecb8bf28eb 23116 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23117 add_node(v7, a, AST_DEBUGGER);
Marko Mikulicic 0:c0ecb8bf28eb 23118 break;
Marko Mikulicic 0:c0ecb8bf28eb 23119 case TOK_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 23120 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23121 CALL_PARSE_VAR(fid_p_stat_9);
Marko Mikulicic 0:c0ecb8bf28eb 23122 break;
Marko Mikulicic 0:c0ecb8bf28eb 23123 case TOK_IDENTIFIER:
Marko Mikulicic 0:c0ecb8bf28eb 23124 if (lookahead(v7) == TOK_COLON) {
Marko Mikulicic 0:c0ecb8bf28eb 23125 add_inlined_node(v7, a, AST_LABEL, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23126 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23127 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23128 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23129 }
Marko Mikulicic 0:c0ecb8bf28eb 23130 /* fall through */
Marko Mikulicic 0:c0ecb8bf28eb 23131 default:
Marko Mikulicic 0:c0ecb8bf28eb 23132 CALL_PARSE_EXPRESSION(fid_p_stat_1);
Marko Mikulicic 0:c0ecb8bf28eb 23133 break;
Marko Mikulicic 0:c0ecb8bf28eb 23134 }
Marko Mikulicic 0:c0ecb8bf28eb 23135
Marko Mikulicic 0:c0ecb8bf28eb 23136 if (end_of_statement(v7) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 23137 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23138 }
Marko Mikulicic 0:c0ecb8bf28eb 23139 ACCEPT(TOK_SEMICOLON); /* swallow optional semicolon */
Marko Mikulicic 0:c0ecb8bf28eb 23140 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23141 }
Marko Mikulicic 0:c0ecb8bf28eb 23142
Marko Mikulicic 0:c0ecb8bf28eb 23143 /* static enum v7_err parse_expression(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23144 fid_parse_expression :
Marko Mikulicic 0:c0ecb8bf28eb 23145 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23146 #define L CR_CUR_LOCALS_PT(fid_parse_expression_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23147 {
Marko Mikulicic 0:c0ecb8bf28eb 23148 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23149 L->group = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23150 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 23151 CALL_PARSE_ASSIGN(fid_p_expr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23152 if (ACCEPT(TOK_COMMA)) {
Marko Mikulicic 0:c0ecb8bf28eb 23153 L->group = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23154 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23155 break;
Marko Mikulicic 0:c0ecb8bf28eb 23156 }
Marko Mikulicic 0:c0ecb8bf28eb 23157 }
Marko Mikulicic 0:c0ecb8bf28eb 23158 if (L->group) {
Marko Mikulicic 0:c0ecb8bf28eb 23159 insert_node(v7, a, L->pos, AST_SEQ);
Marko Mikulicic 0:c0ecb8bf28eb 23160 }
Marko Mikulicic 0:c0ecb8bf28eb 23161 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23162 }
Marko Mikulicic 0:c0ecb8bf28eb 23163
Marko Mikulicic 0:c0ecb8bf28eb 23164 /* static enum v7_err parse_assign(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23165 fid_parse_assign :
Marko Mikulicic 0:c0ecb8bf28eb 23166 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23167 #define L CR_CUR_LOCALS_PT(fid_parse_assign_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23168 {
Marko Mikulicic 0:c0ecb8bf28eb 23169 CALL_PARSE_BINARY(0, a->mbuf.len, fid_p_assign_1);
Marko Mikulicic 0:c0ecb8bf28eb 23170 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23171 }
Marko Mikulicic 0:c0ecb8bf28eb 23172
Marko Mikulicic 0:c0ecb8bf28eb 23173 /*
Marko Mikulicic 0:c0ecb8bf28eb 23174 * static enum v7_err parse_binary(struct v7 *v7, struct ast *a, int level,
Marko Mikulicic 0:c0ecb8bf28eb 23175 * ast_off_t pos)
Marko Mikulicic 0:c0ecb8bf28eb 23176 */
Marko Mikulicic 0:c0ecb8bf28eb 23177 #if 1
Marko Mikulicic 0:c0ecb8bf28eb 23178 fid_parse_binary :
Marko Mikulicic 0:c0ecb8bf28eb 23179 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23180 #define L CR_CUR_LOCALS_PT(fid_parse_binary_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23181 {
Marko Mikulicic 0:c0ecb8bf28eb 23182 /*
Marko Mikulicic 0:c0ecb8bf28eb 23183 * Note: we use macro CUR_POS instead of a local variable, since this
Marko Mikulicic 0:c0ecb8bf28eb 23184 * function is called really a lot, so, each byte on stack frame counts.
Marko Mikulicic 0:c0ecb8bf28eb 23185 *
Marko Mikulicic 0:c0ecb8bf28eb 23186 * It will work a bit slower of course, but slowness is not a problem
Marko Mikulicic 0:c0ecb8bf28eb 23187 */
Marko Mikulicic 0:c0ecb8bf28eb 23188 #define CUR_POS ((L->level > L->arg.min_level) ? L->saved_mbuf_len : L->arg.pos)
Marko Mikulicic 0:c0ecb8bf28eb 23189 L->saved_mbuf_len = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23190
Marko Mikulicic 0:c0ecb8bf28eb 23191 CALL_PARSE_PREFIX(fid_p_binary_6);
Marko Mikulicic 0:c0ecb8bf28eb 23192
Marko Mikulicic 0:c0ecb8bf28eb 23193 for (L->level = (int) ARRAY_SIZE(levels) - 1; L->level >= L->arg.min_level;
Marko Mikulicic 0:c0ecb8bf28eb 23194 L->level--) {
Marko Mikulicic 0:c0ecb8bf28eb 23195 for (L->i = 0; L->i < levels[L->level].len; L->i++) {
Marko Mikulicic 0:c0ecb8bf28eb 23196 L->tok = levels[L->level].parts[L->i].start_tok;
Marko Mikulicic 0:c0ecb8bf28eb 23197 L->ast = levels[L->level].parts[L->i].start_ast;
Marko Mikulicic 0:c0ecb8bf28eb 23198 do {
Marko Mikulicic 0:c0ecb8bf28eb 23199 if (v7->pstate.inhibit_in && L->tok == TOK_IN) {
Marko Mikulicic 0:c0ecb8bf28eb 23200 continue;
Marko Mikulicic 0:c0ecb8bf28eb 23201 }
Marko Mikulicic 0:c0ecb8bf28eb 23202
Marko Mikulicic 0:c0ecb8bf28eb 23203 /*
Marko Mikulicic 0:c0ecb8bf28eb 23204 * Ternary operator sits in the middle of the binary operator
Marko Mikulicic 0:c0ecb8bf28eb 23205 * precedence chain. Deal with it as an exception and don't break
Marko Mikulicic 0:c0ecb8bf28eb 23206 * the chain.
Marko Mikulicic 0:c0ecb8bf28eb 23207 */
Marko Mikulicic 0:c0ecb8bf28eb 23208 if (L->tok == TOK_QUESTION && v7->cur_tok == TOK_QUESTION) {
Marko Mikulicic 0:c0ecb8bf28eb 23209 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23210 CALL_PARSE_ASSIGN(fid_p_binary_2);
Marko Mikulicic 0:c0ecb8bf28eb 23211 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23212 CALL_PARSE_ASSIGN(fid_p_binary_3);
Marko Mikulicic 0:c0ecb8bf28eb 23213 insert_node(v7, a, CUR_POS, AST_COND);
Marko Mikulicic 0:c0ecb8bf28eb 23214 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23215 } else if (ACCEPT(L->tok)) {
Marko Mikulicic 0:c0ecb8bf28eb 23216 if (levels[L->level].left_to_right) {
Marko Mikulicic 0:c0ecb8bf28eb 23217 insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast);
Marko Mikulicic 0:c0ecb8bf28eb 23218 CALL_PARSE_BINARY(L->level, CUR_POS, fid_p_binary_4);
Marko Mikulicic 0:c0ecb8bf28eb 23219 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23220 CALL_PARSE_BINARY(L->level, a->mbuf.len, fid_p_binary_5);
Marko Mikulicic 0:c0ecb8bf28eb 23221 insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast);
Marko Mikulicic 0:c0ecb8bf28eb 23222 }
Marko Mikulicic 0:c0ecb8bf28eb 23223 }
Marko Mikulicic 0:c0ecb8bf28eb 23224 } while (L->ast = (enum ast_tag)(L->ast + 1),
Marko Mikulicic 0:c0ecb8bf28eb 23225 L->tok < levels[L->level].parts[L->i].end_tok &&
Marko Mikulicic 0:c0ecb8bf28eb 23226 (L->tok = (enum v7_tok)(L->tok + 1)));
Marko Mikulicic 0:c0ecb8bf28eb 23227 }
Marko Mikulicic 0:c0ecb8bf28eb 23228 }
Marko Mikulicic 0:c0ecb8bf28eb 23229
Marko Mikulicic 0:c0ecb8bf28eb 23230 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23231 #undef CUR_POS
Marko Mikulicic 0:c0ecb8bf28eb 23232 }
Marko Mikulicic 0:c0ecb8bf28eb 23233 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23234
Marko Mikulicic 0:c0ecb8bf28eb 23235 /* enum v7_err parse_prefix(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23236 fid_parse_prefix :
Marko Mikulicic 0:c0ecb8bf28eb 23237 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23238 #define L CR_CUR_LOCALS_PT(fid_parse_prefix_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23239 {
Marko Mikulicic 0:c0ecb8bf28eb 23240 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 23241 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23242 case TOK_PLUS:
Marko Mikulicic 0:c0ecb8bf28eb 23243 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23244 add_node(v7, a, AST_POSITIVE);
Marko Mikulicic 0:c0ecb8bf28eb 23245 break;
Marko Mikulicic 0:c0ecb8bf28eb 23246 case TOK_MINUS:
Marko Mikulicic 0:c0ecb8bf28eb 23247 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23248 add_node(v7, a, AST_NEGATIVE);
Marko Mikulicic 0:c0ecb8bf28eb 23249 break;
Marko Mikulicic 0:c0ecb8bf28eb 23250 case TOK_PLUS_PLUS:
Marko Mikulicic 0:c0ecb8bf28eb 23251 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23252 add_node(v7, a, AST_PREINC);
Marko Mikulicic 0:c0ecb8bf28eb 23253 break;
Marko Mikulicic 0:c0ecb8bf28eb 23254 case TOK_MINUS_MINUS:
Marko Mikulicic 0:c0ecb8bf28eb 23255 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23256 add_node(v7, a, AST_PREDEC);
Marko Mikulicic 0:c0ecb8bf28eb 23257 break;
Marko Mikulicic 0:c0ecb8bf28eb 23258 case TOK_TILDA:
Marko Mikulicic 0:c0ecb8bf28eb 23259 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23260 add_node(v7, a, AST_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 23261 break;
Marko Mikulicic 0:c0ecb8bf28eb 23262 case TOK_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 23263 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23264 add_node(v7, a, AST_LOGICAL_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 23265 break;
Marko Mikulicic 0:c0ecb8bf28eb 23266 case TOK_VOID:
Marko Mikulicic 0:c0ecb8bf28eb 23267 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23268 add_node(v7, a, AST_VOID);
Marko Mikulicic 0:c0ecb8bf28eb 23269 break;
Marko Mikulicic 0:c0ecb8bf28eb 23270 case TOK_DELETE:
Marko Mikulicic 0:c0ecb8bf28eb 23271 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23272 add_node(v7, a, AST_DELETE);
Marko Mikulicic 0:c0ecb8bf28eb 23273 break;
Marko Mikulicic 0:c0ecb8bf28eb 23274 case TOK_TYPEOF:
Marko Mikulicic 0:c0ecb8bf28eb 23275 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23276 add_node(v7, a, AST_TYPEOF);
Marko Mikulicic 0:c0ecb8bf28eb 23277 break;
Marko Mikulicic 0:c0ecb8bf28eb 23278 default:
Marko Mikulicic 0:c0ecb8bf28eb 23279 CALL_PARSE_POSTFIX(fid_p_prefix_1);
Marko Mikulicic 0:c0ecb8bf28eb 23280 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23281 }
Marko Mikulicic 0:c0ecb8bf28eb 23282 }
Marko Mikulicic 0:c0ecb8bf28eb 23283 }
Marko Mikulicic 0:c0ecb8bf28eb 23284
Marko Mikulicic 0:c0ecb8bf28eb 23285 /* static enum v7_err parse_postfix(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23286 fid_parse_postfix :
Marko Mikulicic 0:c0ecb8bf28eb 23287 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23288 #define L CR_CUR_LOCALS_PT(fid_parse_postfix_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23289 {
Marko Mikulicic 0:c0ecb8bf28eb 23290 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23291 CALL_PARSE_CALLEXPR(fid_p_postfix_1);
Marko Mikulicic 0:c0ecb8bf28eb 23292
Marko Mikulicic 0:c0ecb8bf28eb 23293 if (v7->after_newline) {
Marko Mikulicic 0:c0ecb8bf28eb 23294 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23295 }
Marko Mikulicic 0:c0ecb8bf28eb 23296 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23297 case TOK_PLUS_PLUS:
Marko Mikulicic 0:c0ecb8bf28eb 23298 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23299 insert_node(v7, a, L->pos, AST_POSTINC);
Marko Mikulicic 0:c0ecb8bf28eb 23300 break;
Marko Mikulicic 0:c0ecb8bf28eb 23301 case TOK_MINUS_MINUS:
Marko Mikulicic 0:c0ecb8bf28eb 23302 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23303 insert_node(v7, a, L->pos, AST_POSTDEC);
Marko Mikulicic 0:c0ecb8bf28eb 23304 break;
Marko Mikulicic 0:c0ecb8bf28eb 23305 default:
Marko Mikulicic 0:c0ecb8bf28eb 23306 break; /* nothing */
Marko Mikulicic 0:c0ecb8bf28eb 23307 }
Marko Mikulicic 0:c0ecb8bf28eb 23308 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23309 }
Marko Mikulicic 0:c0ecb8bf28eb 23310
Marko Mikulicic 0:c0ecb8bf28eb 23311 /* static enum v7_err parse_callexpr(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23312 fid_parse_callexpr :
Marko Mikulicic 0:c0ecb8bf28eb 23313 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23314 #define L CR_CUR_LOCALS_PT(fid_parse_callexpr_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23315 {
Marko Mikulicic 0:c0ecb8bf28eb 23316 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23317 CALL_PARSE_NEWEXPR(fid_p_callexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23318
Marko Mikulicic 0:c0ecb8bf28eb 23319 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 23320 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23321 case TOK_DOT:
Marko Mikulicic 0:c0ecb8bf28eb 23322 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23323 CALL_PARSE_MEMBER(L->pos, fid_p_callexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 23324 break;
Marko Mikulicic 0:c0ecb8bf28eb 23325 case TOK_OPEN_PAREN:
Marko Mikulicic 0:c0ecb8bf28eb 23326 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23327 CALL_PARSE_ARGLIST(fid_p_callexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 23328 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23329 insert_node(v7, a, L->pos, AST_CALL);
Marko Mikulicic 0:c0ecb8bf28eb 23330 break;
Marko Mikulicic 0:c0ecb8bf28eb 23331 default:
Marko Mikulicic 0:c0ecb8bf28eb 23332 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23333 }
Marko Mikulicic 0:c0ecb8bf28eb 23334 }
Marko Mikulicic 0:c0ecb8bf28eb 23335 }
Marko Mikulicic 0:c0ecb8bf28eb 23336
Marko Mikulicic 0:c0ecb8bf28eb 23337 /* static enum v7_err parse_newexpr(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23338 fid_parse_newexpr :
Marko Mikulicic 0:c0ecb8bf28eb 23339 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23340 #define L CR_CUR_LOCALS_PT(fid_parse_newexpr_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23341 {
Marko Mikulicic 0:c0ecb8bf28eb 23342 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23343 case TOK_NEW:
Marko Mikulicic 0:c0ecb8bf28eb 23344 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23345 L->start = add_node(v7, a, AST_NEW);
Marko Mikulicic 0:c0ecb8bf28eb 23346 CALL_PARSE_MEMBEREXPR(fid_p_newexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 23347 if (ACCEPT(TOK_OPEN_PAREN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23348 CALL_PARSE_ARGLIST(fid_p_newexpr_4);
Marko Mikulicic 0:c0ecb8bf28eb 23349 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23350 }
Marko Mikulicic 0:c0ecb8bf28eb 23351 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23352 break;
Marko Mikulicic 0:c0ecb8bf28eb 23353 case TOK_FUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 23354 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23355 CALL_PARSE_FUNCDECL(0, 0, fid_p_newexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 23356 break;
Marko Mikulicic 0:c0ecb8bf28eb 23357 default:
Marko Mikulicic 0:c0ecb8bf28eb 23358 CALL_PARSE_TERMINAL(fid_p_newexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23359 break;
Marko Mikulicic 0:c0ecb8bf28eb 23360 }
Marko Mikulicic 0:c0ecb8bf28eb 23361 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23362 }
Marko Mikulicic 0:c0ecb8bf28eb 23363
Marko Mikulicic 0:c0ecb8bf28eb 23364 /* static enum v7_err parse_terminal(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23365 fid_parse_terminal :
Marko Mikulicic 0:c0ecb8bf28eb 23366 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23367 #define L CR_CUR_LOCALS_PT(fid_parse_terminal_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23368 {
Marko Mikulicic 0:c0ecb8bf28eb 23369 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23370 case TOK_OPEN_PAREN:
Marko Mikulicic 0:c0ecb8bf28eb 23371 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23372 CALL_PARSE_EXPRESSION(fid_p_terminal_1);
Marko Mikulicic 0:c0ecb8bf28eb 23373 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23374 break;
Marko Mikulicic 0:c0ecb8bf28eb 23375 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23376 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23377 L->start = add_node(v7, a, AST_ARRAY);
Marko Mikulicic 0:c0ecb8bf28eb 23378 while (v7->cur_tok != TOK_CLOSE_BRACKET) {
Marko Mikulicic 0:c0ecb8bf28eb 23379 if (v7->cur_tok == TOK_COMMA) {
Marko Mikulicic 0:c0ecb8bf28eb 23380 /* Array literals allow missing elements, e.g. [,,1,] */
Marko Mikulicic 0:c0ecb8bf28eb 23381 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23382 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23383 CALL_PARSE_ASSIGN(fid_p_terminal_2);
Marko Mikulicic 0:c0ecb8bf28eb 23384 }
Marko Mikulicic 0:c0ecb8bf28eb 23385 ACCEPT(TOK_COMMA);
Marko Mikulicic 0:c0ecb8bf28eb 23386 }
Marko Mikulicic 0:c0ecb8bf28eb 23387 EXPECT(TOK_CLOSE_BRACKET);
Marko Mikulicic 0:c0ecb8bf28eb 23388 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23389 break;
Marko Mikulicic 0:c0ecb8bf28eb 23390 case TOK_OPEN_CURLY:
Marko Mikulicic 0:c0ecb8bf28eb 23391 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23392 L->start = add_node(v7, a, AST_OBJECT);
Marko Mikulicic 0:c0ecb8bf28eb 23393 if (v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23394 do {
Marko Mikulicic 0:c0ecb8bf28eb 23395 if (v7->cur_tok == TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23396 break;
Marko Mikulicic 0:c0ecb8bf28eb 23397 }
Marko Mikulicic 0:c0ecb8bf28eb 23398 CALL_PARSE_PROP(fid_p_terminal_3);
Marko Mikulicic 0:c0ecb8bf28eb 23399 } while (ACCEPT(TOK_COMMA));
Marko Mikulicic 0:c0ecb8bf28eb 23400 }
Marko Mikulicic 0:c0ecb8bf28eb 23401 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23402 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23403 break;
Marko Mikulicic 0:c0ecb8bf28eb 23404 case TOK_THIS:
Marko Mikulicic 0:c0ecb8bf28eb 23405 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23406 add_node(v7, a, AST_THIS);
Marko Mikulicic 0:c0ecb8bf28eb 23407 break;
Marko Mikulicic 0:c0ecb8bf28eb 23408 case TOK_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 23409 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23410 add_node(v7, a, AST_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 23411 break;
Marko Mikulicic 0:c0ecb8bf28eb 23412 case TOK_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 23413 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23414 add_node(v7, a, AST_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 23415 break;
Marko Mikulicic 0:c0ecb8bf28eb 23416 case TOK_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 23417 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23418 add_node(v7, a, AST_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 23419 break;
Marko Mikulicic 0:c0ecb8bf28eb 23420 case TOK_STRING_LITERAL:
Marko Mikulicic 0:c0ecb8bf28eb 23421 add_inlined_node(v7, a, AST_STRING, v7->tok + 1, v7->tok_len - 2);
Marko Mikulicic 0:c0ecb8bf28eb 23422 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23423 break;
Marko Mikulicic 0:c0ecb8bf28eb 23424 case TOK_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 23425 add_inlined_node(v7, a, AST_NUM, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23426 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23427 break;
Marko Mikulicic 0:c0ecb8bf28eb 23428 case TOK_REGEX_LITERAL:
Marko Mikulicic 0:c0ecb8bf28eb 23429 add_inlined_node(v7, a, AST_REGEX, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23430 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23431 break;
Marko Mikulicic 0:c0ecb8bf28eb 23432 case TOK_IDENTIFIER:
Marko Mikulicic 0:c0ecb8bf28eb 23433 if (v7->tok_len == 9 && strncmp(v7->tok, "undefined", v7->tok_len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 23434 add_node(v7, a, AST_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 23435 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23436 break;
Marko Mikulicic 0:c0ecb8bf28eb 23437 }
Marko Mikulicic 0:c0ecb8bf28eb 23438 /* fall through */
Marko Mikulicic 0:c0ecb8bf28eb 23439 default:
Marko Mikulicic 0:c0ecb8bf28eb 23440 CALL_PARSE_IDENT(fid_p_terminal_4);
Marko Mikulicic 0:c0ecb8bf28eb 23441 }
Marko Mikulicic 0:c0ecb8bf28eb 23442 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23443 }
Marko Mikulicic 0:c0ecb8bf28eb 23444
Marko Mikulicic 0:c0ecb8bf28eb 23445 /* static enum v7_err parse_block(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23446 fid_parse_block :
Marko Mikulicic 0:c0ecb8bf28eb 23447 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23448 #define L CR_CUR_LOCALS_PT(fid_parse_block_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23449 {
Marko Mikulicic 0:c0ecb8bf28eb 23450 EXPECT(TOK_OPEN_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23451 CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_block_1);
Marko Mikulicic 0:c0ecb8bf28eb 23452 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23453 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23454 }
Marko Mikulicic 0:c0ecb8bf28eb 23455
Marko Mikulicic 0:c0ecb8bf28eb 23456 /* static enum v7_err parse_if(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23457 fid_parse_if :
Marko Mikulicic 0:c0ecb8bf28eb 23458 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23459 #define L CR_CUR_LOCALS_PT(fid_parse_if_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23460 {
Marko Mikulicic 0:c0ecb8bf28eb 23461 L->start = add_node(v7, a, AST_IF);
Marko Mikulicic 0:c0ecb8bf28eb 23462 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23463 CALL_PARSE_EXPRESSION(fid_p_if_1);
Marko Mikulicic 0:c0ecb8bf28eb 23464 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23465 CALL_PARSE_STATEMENT(fid_p_if_2);
Marko Mikulicic 0:c0ecb8bf28eb 23466 ast_set_skip(a, L->start, AST_END_IF_TRUE_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23467 if (ACCEPT(TOK_ELSE)) {
Marko Mikulicic 0:c0ecb8bf28eb 23468 CALL_PARSE_STATEMENT(fid_p_if_3);
Marko Mikulicic 0:c0ecb8bf28eb 23469 }
Marko Mikulicic 0:c0ecb8bf28eb 23470 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23471 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23472 }
Marko Mikulicic 0:c0ecb8bf28eb 23473
Marko Mikulicic 0:c0ecb8bf28eb 23474 /* static enum v7_err parse_while(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23475 fid_parse_while :
Marko Mikulicic 0:c0ecb8bf28eb 23476 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23477 #define L CR_CUR_LOCALS_PT(fid_parse_while_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23478 {
Marko Mikulicic 0:c0ecb8bf28eb 23479 L->start = add_node(v7, a, AST_WHILE);
Marko Mikulicic 0:c0ecb8bf28eb 23480 L->saved_in_loop = v7->pstate.in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23481 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23482 CALL_PARSE_EXPRESSION(fid_p_while_1);
Marko Mikulicic 0:c0ecb8bf28eb 23483 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23484 v7->pstate.in_loop = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23485 CALL_PARSE_STATEMENT(fid_p_while_2);
Marko Mikulicic 0:c0ecb8bf28eb 23486 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23487 v7->pstate.in_loop = L->saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23488 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23489 }
Marko Mikulicic 0:c0ecb8bf28eb 23490
Marko Mikulicic 0:c0ecb8bf28eb 23491 /* static enum v7_err parse_ident(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23492 fid_parse_ident :
Marko Mikulicic 0:c0ecb8bf28eb 23493 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23494 #define L CR_CUR_LOCALS_PT(fid_parse_ident_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23495 {
Marko Mikulicic 0:c0ecb8bf28eb 23496 if (v7->cur_tok == TOK_IDENTIFIER) {
Marko Mikulicic 0:c0ecb8bf28eb 23497 add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23498 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23499 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23500 }
Marko Mikulicic 0:c0ecb8bf28eb 23501 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23502 }
Marko Mikulicic 0:c0ecb8bf28eb 23503
Marko Mikulicic 0:c0ecb8bf28eb 23504 /*
Marko Mikulicic 0:c0ecb8bf28eb 23505 * static enum v7_err parse_ident_allow_reserved_words(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 23506 * struct ast *a)
Marko Mikulicic 0:c0ecb8bf28eb 23507 *
Marko Mikulicic 0:c0ecb8bf28eb 23508 */
Marko Mikulicic 0:c0ecb8bf28eb 23509 fid_parse_ident_allow_reserved_words :
Marko Mikulicic 0:c0ecb8bf28eb 23510 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23511 #define L CR_CUR_LOCALS_PT(fid_parse_ident_allow_reserved_words_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23512 {
Marko Mikulicic 0:c0ecb8bf28eb 23513 /* Allow reserved words as property names. */
Marko Mikulicic 0:c0ecb8bf28eb 23514 if (is_reserved_word_token(v7->cur_tok)) {
Marko Mikulicic 0:c0ecb8bf28eb 23515 add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23516 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23517 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23518 CALL_PARSE_IDENT(fid_p_ident_arw_1);
Marko Mikulicic 0:c0ecb8bf28eb 23519 }
Marko Mikulicic 0:c0ecb8bf28eb 23520 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23521 }
Marko Mikulicic 0:c0ecb8bf28eb 23522
Marko Mikulicic 0:c0ecb8bf28eb 23523 /* static enum v7_err parse_funcdecl(struct v7 *, struct ast *, int, int) */
Marko Mikulicic 0:c0ecb8bf28eb 23524 fid_parse_funcdecl :
Marko Mikulicic 0:c0ecb8bf28eb 23525 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23526 #define L CR_CUR_LOCALS_PT(fid_parse_funcdecl_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23527 {
Marko Mikulicic 0:c0ecb8bf28eb 23528 L->start = add_node(v7, a, AST_FUNC);
Marko Mikulicic 0:c0ecb8bf28eb 23529 L->outer_last_var_node = v7->last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 23530 L->saved_in_function = v7->pstate.in_function;
Marko Mikulicic 0:c0ecb8bf28eb 23531 L->saved_in_strict = v7->pstate.in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 23532
Marko Mikulicic 0:c0ecb8bf28eb 23533 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 23534 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23535
Marko Mikulicic 0:c0ecb8bf28eb 23536 CR_TRY(fid_p_funcdecl_2);
Marko Mikulicic 0:c0ecb8bf28eb 23537 {
Marko Mikulicic 0:c0ecb8bf28eb 23538 if (L->arg.reserved_name) {
Marko Mikulicic 0:c0ecb8bf28eb 23539 CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(fid_p_funcdecl_1);
Marko Mikulicic 0:c0ecb8bf28eb 23540 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23541 CALL_PARSE_IDENT(fid_p_funcdecl_9);
Marko Mikulicic 0:c0ecb8bf28eb 23542 }
Marko Mikulicic 0:c0ecb8bf28eb 23543 }
Marko Mikulicic 0:c0ecb8bf28eb 23544 CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_2, fid_p_funcdecl_3);
Marko Mikulicic 0:c0ecb8bf28eb 23545 {
Marko Mikulicic 0:c0ecb8bf28eb 23546 if (L->arg.require_named) {
Marko Mikulicic 0:c0ecb8bf28eb 23547 /* function name is required, so, rethrow SYNTAX ERROR */
Marko Mikulicic 0:c0ecb8bf28eb 23548 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23549 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23550 /* it's ok not to have a function name, just insert NOP */
Marko Mikulicic 0:c0ecb8bf28eb 23551 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23552 }
Marko Mikulicic 0:c0ecb8bf28eb 23553 }
Marko Mikulicic 0:c0ecb8bf28eb 23554 CR_ENDCATCH(fid_p_funcdecl_3);
Marko Mikulicic 0:c0ecb8bf28eb 23555
Marko Mikulicic 0:c0ecb8bf28eb 23556 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23557 CALL_PARSE_ARGLIST(fid_p_funcdecl_4);
Marko Mikulicic 0:c0ecb8bf28eb 23558 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23559 ast_set_skip(a, L->start, AST_FUNC_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23560 v7->pstate.in_function = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23561 EXPECT(TOK_OPEN_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23562
Marko Mikulicic 0:c0ecb8bf28eb 23563 CR_TRY(fid_p_funcdecl_5);
Marko Mikulicic 0:c0ecb8bf28eb 23564 {
Marko Mikulicic 0:c0ecb8bf28eb 23565 CALL_PARSE_USE_STRICT(fid_p_funcdecl_7);
Marko Mikulicic 0:c0ecb8bf28eb 23566 v7->pstate.in_strict = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23567 }
Marko Mikulicic 0:c0ecb8bf28eb 23568 CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_5, fid_p_funcdecl_6);
Marko Mikulicic 0:c0ecb8bf28eb 23569 CR_ENDCATCH(fid_p_funcdecl_6);
Marko Mikulicic 0:c0ecb8bf28eb 23570
Marko Mikulicic 0:c0ecb8bf28eb 23571 CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_funcdecl_8);
Marko Mikulicic 0:c0ecb8bf28eb 23572 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23573 v7->pstate.in_strict = L->saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 23574 v7->pstate.in_function = L->saved_in_function;
Marko Mikulicic 0:c0ecb8bf28eb 23575 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23576 v7->last_var_node = L->outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 23577
Marko Mikulicic 0:c0ecb8bf28eb 23578 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23579 }
Marko Mikulicic 0:c0ecb8bf28eb 23580
Marko Mikulicic 0:c0ecb8bf28eb 23581 /* static enum v7_err parse_arglist(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23582 fid_parse_arglist :
Marko Mikulicic 0:c0ecb8bf28eb 23583 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23584 #define L CR_CUR_LOCALS_PT(fid_parse_arglist_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23585 {
Marko Mikulicic 0:c0ecb8bf28eb 23586 if (v7->cur_tok != TOK_CLOSE_PAREN) {
Marko Mikulicic 0:c0ecb8bf28eb 23587 do {
Marko Mikulicic 0:c0ecb8bf28eb 23588 CALL_PARSE_ASSIGN(fid_p_arglist_1);
Marko Mikulicic 0:c0ecb8bf28eb 23589 } while (ACCEPT(TOK_COMMA));
Marko Mikulicic 0:c0ecb8bf28eb 23590 }
Marko Mikulicic 0:c0ecb8bf28eb 23591 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23592 }
Marko Mikulicic 0:c0ecb8bf28eb 23593
Marko Mikulicic 0:c0ecb8bf28eb 23594 /*
Marko Mikulicic 0:c0ecb8bf28eb 23595 * static enum v7_err parse_member(struct v7 *v7, struct ast *a, ast_off_t pos)
Marko Mikulicic 0:c0ecb8bf28eb 23596 */
Marko Mikulicic 0:c0ecb8bf28eb 23597 fid_parse_member :
Marko Mikulicic 0:c0ecb8bf28eb 23598 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23599 #define L CR_CUR_LOCALS_PT(fid_parse_member_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23600 {
Marko Mikulicic 0:c0ecb8bf28eb 23601 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23602 case TOK_DOT:
Marko Mikulicic 0:c0ecb8bf28eb 23603 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23604 /* Allow reserved words as member identifiers */
Marko Mikulicic 0:c0ecb8bf28eb 23605 if (is_reserved_word_token(v7->cur_tok) ||
Marko Mikulicic 0:c0ecb8bf28eb 23606 v7->cur_tok == TOK_IDENTIFIER) {
Marko Mikulicic 0:c0ecb8bf28eb 23607 insert_inlined_node(v7, a, L->arg.pos, AST_MEMBER, v7->tok,
Marko Mikulicic 0:c0ecb8bf28eb 23608 v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23609 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23610 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23611 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23612 }
Marko Mikulicic 0:c0ecb8bf28eb 23613 break;
Marko Mikulicic 0:c0ecb8bf28eb 23614 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23615 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23616 CALL_PARSE_EXPRESSION(fid_p_member_1);
Marko Mikulicic 0:c0ecb8bf28eb 23617 EXPECT(TOK_CLOSE_BRACKET);
Marko Mikulicic 0:c0ecb8bf28eb 23618 insert_node(v7, a, L->arg.pos, AST_INDEX);
Marko Mikulicic 0:c0ecb8bf28eb 23619 break;
Marko Mikulicic 0:c0ecb8bf28eb 23620 default:
Marko Mikulicic 0:c0ecb8bf28eb 23621 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23622 }
Marko Mikulicic 0:c0ecb8bf28eb 23623 /* not necessary, but let it be anyway */
Marko Mikulicic 0:c0ecb8bf28eb 23624 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23625 }
Marko Mikulicic 0:c0ecb8bf28eb 23626
Marko Mikulicic 0:c0ecb8bf28eb 23627 /* static enum v7_err parse_memberexpr(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23628 fid_parse_memberexpr :
Marko Mikulicic 0:c0ecb8bf28eb 23629 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23630 #define L CR_CUR_LOCALS_PT(fid_parse_memberexpr_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23631 {
Marko Mikulicic 0:c0ecb8bf28eb 23632 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23633 CALL_PARSE_NEWEXPR(fid_p_memberexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23634
Marko Mikulicic 0:c0ecb8bf28eb 23635 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 23636 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23637 case TOK_DOT:
Marko Mikulicic 0:c0ecb8bf28eb 23638 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23639 CALL_PARSE_MEMBER(L->pos, fid_p_memberexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 23640 break;
Marko Mikulicic 0:c0ecb8bf28eb 23641 default:
Marko Mikulicic 0:c0ecb8bf28eb 23642 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23643 }
Marko Mikulicic 0:c0ecb8bf28eb 23644 }
Marko Mikulicic 0:c0ecb8bf28eb 23645 }
Marko Mikulicic 0:c0ecb8bf28eb 23646
Marko Mikulicic 0:c0ecb8bf28eb 23647 /* static enum v7_err parse_var(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23648 fid_parse_var :
Marko Mikulicic 0:c0ecb8bf28eb 23649 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23650 #define L CR_CUR_LOCALS_PT(fid_parse_var_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23651 {
Marko Mikulicic 0:c0ecb8bf28eb 23652 L->start = add_node(v7, a, AST_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 23653 ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23654 /* zero out var node pointer */
Marko Mikulicic 0:c0ecb8bf28eb 23655 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23656 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 23657 do {
Marko Mikulicic 0:c0ecb8bf28eb 23658 add_inlined_node(v7, a, AST_VAR_DECL, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23659 EXPECT(TOK_IDENTIFIER);
Marko Mikulicic 0:c0ecb8bf28eb 23660 if (ACCEPT(TOK_ASSIGN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23661 CALL_PARSE_ASSIGN(fid_p_var_1);
Marko Mikulicic 0:c0ecb8bf28eb 23662 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23663 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23664 }
Marko Mikulicic 0:c0ecb8bf28eb 23665 } while (ACCEPT(TOK_COMMA));
Marko Mikulicic 0:c0ecb8bf28eb 23666 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23667 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23668 }
Marko Mikulicic 0:c0ecb8bf28eb 23669
Marko Mikulicic 0:c0ecb8bf28eb 23670 /* static enum v7_err parse_prop(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23671 fid_parse_prop :
Marko Mikulicic 0:c0ecb8bf28eb 23672 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23673 #define L CR_CUR_LOCALS_PT(fid_parse_prop_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23674 {
Marko Mikulicic 0:c0ecb8bf28eb 23675 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 23676 if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 &&
Marko Mikulicic 0:c0ecb8bf28eb 23677 strncmp(v7->tok, "get", v7->tok_len) == 0 && lookahead(v7) != TOK_COLON) {
Marko Mikulicic 0:c0ecb8bf28eb 23678 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23679 add_node(v7, a, AST_GETTER);
Marko Mikulicic 0:c0ecb8bf28eb 23680 CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_1_getter);
Marko Mikulicic 0:c0ecb8bf28eb 23681 } else
Marko Mikulicic 0:c0ecb8bf28eb 23682 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23683 if (v7->cur_tok == TOK_IDENTIFIER && lookahead(v7) == TOK_OPEN_PAREN) {
Marko Mikulicic 0:c0ecb8bf28eb 23684 /* ecmascript 6 feature */
Marko Mikulicic 0:c0ecb8bf28eb 23685 CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_2);
Marko Mikulicic 0:c0ecb8bf28eb 23686 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 23687 } else if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 &&
Marko Mikulicic 0:c0ecb8bf28eb 23688 strncmp(v7->tok, "set", v7->tok_len) == 0 &&
Marko Mikulicic 0:c0ecb8bf28eb 23689 lookahead(v7) != TOK_COLON) {
Marko Mikulicic 0:c0ecb8bf28eb 23690 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23691 add_node(v7, a, AST_SETTER);
Marko Mikulicic 0:c0ecb8bf28eb 23692 CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_3_setter);
Marko Mikulicic 0:c0ecb8bf28eb 23693 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23694 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23695 /* Allow reserved words as property names. */
Marko Mikulicic 0:c0ecb8bf28eb 23696 if (is_reserved_word_token(v7->cur_tok) || v7->cur_tok == TOK_IDENTIFIER ||
Marko Mikulicic 0:c0ecb8bf28eb 23697 v7->cur_tok == TOK_NUMBER) {
Marko Mikulicic 0:c0ecb8bf28eb 23698 add_inlined_node(v7, a, AST_PROP, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23699 } else if (v7->cur_tok == TOK_STRING_LITERAL) {
Marko Mikulicic 0:c0ecb8bf28eb 23700 add_inlined_node(v7, a, AST_PROP, v7->tok + 1, v7->tok_len - 2);
Marko Mikulicic 0:c0ecb8bf28eb 23701 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23702 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23703 }
Marko Mikulicic 0:c0ecb8bf28eb 23704 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23705 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23706 CALL_PARSE_ASSIGN(fid_p_prop_4);
Marko Mikulicic 0:c0ecb8bf28eb 23707 }
Marko Mikulicic 0:c0ecb8bf28eb 23708 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23709 }
Marko Mikulicic 0:c0ecb8bf28eb 23710
Marko Mikulicic 0:c0ecb8bf28eb 23711 /* static enum v7_err parse_dowhile(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23712 fid_parse_dowhile :
Marko Mikulicic 0:c0ecb8bf28eb 23713 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23714 #define L CR_CUR_LOCALS_PT(fid_parse_dowhile_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23715 {
Marko Mikulicic 0:c0ecb8bf28eb 23716 L->start = add_node(v7, a, AST_DOWHILE);
Marko Mikulicic 0:c0ecb8bf28eb 23717 L->saved_in_loop = v7->pstate.in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23718
Marko Mikulicic 0:c0ecb8bf28eb 23719 v7->pstate.in_loop = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23720 CALL_PARSE_STATEMENT(fid_p_dowhile_1);
Marko Mikulicic 0:c0ecb8bf28eb 23721 v7->pstate.in_loop = L->saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23722 ast_set_skip(a, L->start, AST_DO_WHILE_COND_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23723 EXPECT(TOK_WHILE);
Marko Mikulicic 0:c0ecb8bf28eb 23724 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23725 CALL_PARSE_EXPRESSION(fid_p_dowhile_2);
Marko Mikulicic 0:c0ecb8bf28eb 23726 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23727 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23728 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23729 }
Marko Mikulicic 0:c0ecb8bf28eb 23730
Marko Mikulicic 0:c0ecb8bf28eb 23731 /* static enum v7_err parse_for(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23732 fid_parse_for :
Marko Mikulicic 0:c0ecb8bf28eb 23733 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23734 #define L CR_CUR_LOCALS_PT(fid_parse_for_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23735 {
Marko Mikulicic 0:c0ecb8bf28eb 23736 /* TODO(mkm): for of, for each in */
Marko Mikulicic 0:c0ecb8bf28eb 23737 /*
Marko Mikulicic 0:c0ecb8bf28eb 23738 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 23739 int saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23740 */
Marko Mikulicic 0:c0ecb8bf28eb 23741
Marko Mikulicic 0:c0ecb8bf28eb 23742 L->start = add_node(v7, a, AST_FOR);
Marko Mikulicic 0:c0ecb8bf28eb 23743 L->saved_in_loop = v7->pstate.in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23744
Marko Mikulicic 0:c0ecb8bf28eb 23745 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23746
Marko Mikulicic 0:c0ecb8bf28eb 23747 if (parse_optional(v7, a, TOK_SEMICOLON)) {
Marko Mikulicic 0:c0ecb8bf28eb 23748 /*
Marko Mikulicic 0:c0ecb8bf28eb 23749 * TODO(mkm): make this reentrant otherwise this pearl won't parse:
Marko Mikulicic 0:c0ecb8bf28eb 23750 * for((function(){return 1 in o.a ? o : x})().a in [1,2,3])
Marko Mikulicic 0:c0ecb8bf28eb 23751 */
Marko Mikulicic 0:c0ecb8bf28eb 23752 v7->pstate.inhibit_in = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23753 if (ACCEPT(TOK_VAR)) {
Marko Mikulicic 0:c0ecb8bf28eb 23754 CALL_PARSE_VAR(fid_p_for_1);
Marko Mikulicic 0:c0ecb8bf28eb 23755 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23756 CALL_PARSE_EXPRESSION(fid_p_for_2);
Marko Mikulicic 0:c0ecb8bf28eb 23757 }
Marko Mikulicic 0:c0ecb8bf28eb 23758 v7->pstate.inhibit_in = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23759
Marko Mikulicic 0:c0ecb8bf28eb 23760 if (ACCEPT(TOK_IN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23761 CALL_PARSE_EXPRESSION(fid_p_for_3);
Marko Mikulicic 0:c0ecb8bf28eb 23762 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23763 /*
Marko Mikulicic 0:c0ecb8bf28eb 23764 * Assumes that for and for in have the same AST format which is
Marko Mikulicic 0:c0ecb8bf28eb 23765 * suboptimal but avoids the need of fixing up the var offset chain.
Marko Mikulicic 0:c0ecb8bf28eb 23766 * TODO(mkm) improve this
Marko Mikulicic 0:c0ecb8bf28eb 23767 */
Marko Mikulicic 0:c0ecb8bf28eb 23768 ast_modify_tag(a, L->start - 1, AST_FOR_IN);
Marko Mikulicic 0:c0ecb8bf28eb 23769 goto for_loop_body;
Marko Mikulicic 0:c0ecb8bf28eb 23770 }
Marko Mikulicic 0:c0ecb8bf28eb 23771 }
Marko Mikulicic 0:c0ecb8bf28eb 23772
Marko Mikulicic 0:c0ecb8bf28eb 23773 EXPECT(TOK_SEMICOLON);
Marko Mikulicic 0:c0ecb8bf28eb 23774 if (parse_optional(v7, a, TOK_SEMICOLON)) {
Marko Mikulicic 0:c0ecb8bf28eb 23775 CALL_PARSE_EXPRESSION(fid_p_for_4);
Marko Mikulicic 0:c0ecb8bf28eb 23776 }
Marko Mikulicic 0:c0ecb8bf28eb 23777 EXPECT(TOK_SEMICOLON);
Marko Mikulicic 0:c0ecb8bf28eb 23778 if (parse_optional(v7, a, TOK_CLOSE_PAREN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23779 CALL_PARSE_EXPRESSION(fid_p_for_5);
Marko Mikulicic 0:c0ecb8bf28eb 23780 }
Marko Mikulicic 0:c0ecb8bf28eb 23781
Marko Mikulicic 0:c0ecb8bf28eb 23782 for_loop_body:
Marko Mikulicic 0:c0ecb8bf28eb 23783 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23784 ast_set_skip(a, L->start, AST_FOR_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23785 v7->pstate.in_loop = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23786 CALL_PARSE_STATEMENT(fid_p_for_6);
Marko Mikulicic 0:c0ecb8bf28eb 23787 v7->pstate.in_loop = L->saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23788 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23789 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23790 }
Marko Mikulicic 0:c0ecb8bf28eb 23791
Marko Mikulicic 0:c0ecb8bf28eb 23792 /* static enum v7_err parse_try(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23793 fid_parse_try :
Marko Mikulicic 0:c0ecb8bf28eb 23794 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23795 #define L CR_CUR_LOCALS_PT(fid_parse_try_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23796 {
Marko Mikulicic 0:c0ecb8bf28eb 23797 L->start = add_node(v7, a, AST_TRY);
Marko Mikulicic 0:c0ecb8bf28eb 23798 L->catch_or_finally = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23799 CALL_PARSE_BLOCK(fid_p_try_1);
Marko Mikulicic 0:c0ecb8bf28eb 23800 ast_set_skip(a, L->start, AST_TRY_CATCH_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23801 if (ACCEPT(TOK_CATCH)) {
Marko Mikulicic 0:c0ecb8bf28eb 23802 L->catch_or_finally = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23803 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23804 CALL_PARSE_IDENT(fid_p_try_2);
Marko Mikulicic 0:c0ecb8bf28eb 23805 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23806 CALL_PARSE_BLOCK(fid_p_try_3);
Marko Mikulicic 0:c0ecb8bf28eb 23807 }
Marko Mikulicic 0:c0ecb8bf28eb 23808 ast_set_skip(a, L->start, AST_TRY_FINALLY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23809 if (ACCEPT(TOK_FINALLY)) {
Marko Mikulicic 0:c0ecb8bf28eb 23810 L->catch_or_finally = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23811 CALL_PARSE_BLOCK(fid_p_try_4);
Marko Mikulicic 0:c0ecb8bf28eb 23812 }
Marko Mikulicic 0:c0ecb8bf28eb 23813 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23814
Marko Mikulicic 0:c0ecb8bf28eb 23815 /* make sure `catch` and `finally` aren't both missing */
Marko Mikulicic 0:c0ecb8bf28eb 23816 if (!L->catch_or_finally) {
Marko Mikulicic 0:c0ecb8bf28eb 23817 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23818 }
Marko Mikulicic 0:c0ecb8bf28eb 23819
Marko Mikulicic 0:c0ecb8bf28eb 23820 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23821 }
Marko Mikulicic 0:c0ecb8bf28eb 23822
Marko Mikulicic 0:c0ecb8bf28eb 23823 /* static enum v7_err parse_switch(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23824 fid_parse_switch :
Marko Mikulicic 0:c0ecb8bf28eb 23825 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23826 #define L CR_CUR_LOCALS_PT(fid_parse_switch_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23827 {
Marko Mikulicic 0:c0ecb8bf28eb 23828 L->start = add_node(v7, a, AST_SWITCH);
Marko Mikulicic 0:c0ecb8bf28eb 23829 L->saved_in_switch = v7->pstate.in_switch;
Marko Mikulicic 0:c0ecb8bf28eb 23830
Marko Mikulicic 0:c0ecb8bf28eb 23831 ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP); /* clear out */
Marko Mikulicic 0:c0ecb8bf28eb 23832 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23833 CALL_PARSE_EXPRESSION(fid_p_switch_1);
Marko Mikulicic 0:c0ecb8bf28eb 23834 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23835 EXPECT(TOK_OPEN_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23836 v7->pstate.in_switch = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23837 while (v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23838 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23839 case TOK_CASE:
Marko Mikulicic 0:c0ecb8bf28eb 23840 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23841 L->case_start = add_node(v7, a, AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 23842 CALL_PARSE_EXPRESSION(fid_p_switch_2);
Marko Mikulicic 0:c0ecb8bf28eb 23843 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23844 while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT &&
Marko Mikulicic 0:c0ecb8bf28eb 23845 v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23846 CALL_PARSE_STATEMENT(fid_p_switch_3);
Marko Mikulicic 0:c0ecb8bf28eb 23847 }
Marko Mikulicic 0:c0ecb8bf28eb 23848 ast_set_skip(a, L->case_start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23849 break;
Marko Mikulicic 0:c0ecb8bf28eb 23850 case TOK_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 23851 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23852 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23853 ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23854 L->case_start = add_node(v7, a, AST_DEFAULT);
Marko Mikulicic 0:c0ecb8bf28eb 23855 while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT &&
Marko Mikulicic 0:c0ecb8bf28eb 23856 v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23857 CALL_PARSE_STATEMENT(fid_p_switch_4);
Marko Mikulicic 0:c0ecb8bf28eb 23858 }
Marko Mikulicic 0:c0ecb8bf28eb 23859 ast_set_skip(a, L->case_start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23860 break;
Marko Mikulicic 0:c0ecb8bf28eb 23861 default:
Marko Mikulicic 0:c0ecb8bf28eb 23862 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23863 }
Marko Mikulicic 0:c0ecb8bf28eb 23864 }
Marko Mikulicic 0:c0ecb8bf28eb 23865 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23866 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23867 v7->pstate.in_switch = L->saved_in_switch;
Marko Mikulicic 0:c0ecb8bf28eb 23868 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23869 }
Marko Mikulicic 0:c0ecb8bf28eb 23870
Marko Mikulicic 0:c0ecb8bf28eb 23871 /* static enum v7_err parse_with(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23872 fid_parse_with :
Marko Mikulicic 0:c0ecb8bf28eb 23873 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23874 #define L CR_CUR_LOCALS_PT(fid_parse_with_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23875 {
Marko Mikulicic 0:c0ecb8bf28eb 23876 L->start = add_node(v7, a, AST_WITH);
Marko Mikulicic 0:c0ecb8bf28eb 23877 if (v7->pstate.in_strict) {
Marko Mikulicic 0:c0ecb8bf28eb 23878 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23879 }
Marko Mikulicic 0:c0ecb8bf28eb 23880 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23881 CALL_PARSE_EXPRESSION(fid_p_with_1);
Marko Mikulicic 0:c0ecb8bf28eb 23882 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23883 CALL_PARSE_STATEMENT(fid_p_with_2);
Marko Mikulicic 0:c0ecb8bf28eb 23884 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23885 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23886 }
Marko Mikulicic 0:c0ecb8bf28eb 23887
Marko Mikulicic 0:c0ecb8bf28eb 23888 fid_none:
Marko Mikulicic 0:c0ecb8bf28eb 23889 /* stack is empty, so we're done; return */
Marko Mikulicic 0:c0ecb8bf28eb 23890 return rc;
Marko Mikulicic 0:c0ecb8bf28eb 23891 }
Marko Mikulicic 0:c0ecb8bf28eb 23892
Marko Mikulicic 0:c0ecb8bf28eb 23893 V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src,
Marko Mikulicic 0:c0ecb8bf28eb 23894 size_t src_len, int is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 23895 enum v7_err rcode;
Marko Mikulicic 0:c0ecb8bf28eb 23896 const char *error_msg = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 23897 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 23898 struct cr_ctx cr_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 23899 union user_arg_ret arg_retval;
Marko Mikulicic 0:c0ecb8bf28eb 23900 enum cr_status rc;
Marko Mikulicic 0:c0ecb8bf28eb 23901 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 23902 struct stack_track_ctx stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 23903 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23904 int saved_line_no = v7->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 23905
Marko Mikulicic 0:c0ecb8bf28eb 23906 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 23907 v7_stack_track_start(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 23908 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23909
Marko Mikulicic 0:c0ecb8bf28eb 23910 v7->pstate.source_code = v7->pstate.pc = src;
Marko Mikulicic 0:c0ecb8bf28eb 23911 v7->pstate.src_end = src + src_len;
Marko Mikulicic 0:c0ecb8bf28eb 23912 v7->pstate.file_name = "<stdin>";
Marko Mikulicic 0:c0ecb8bf28eb 23913 v7->pstate.line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23914 v7->pstate.in_function = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23915 v7->pstate.in_loop = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23916 v7->pstate.in_switch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23917
Marko Mikulicic 0:c0ecb8bf28eb 23918 /*
Marko Mikulicic 0:c0ecb8bf28eb 23919 * TODO(dfrank): `v7->parser.line_no` vs `v7->line_no` is confusing. probaby
Marko Mikulicic 0:c0ecb8bf28eb 23920 * we need to refactor it.
Marko Mikulicic 0:c0ecb8bf28eb 23921 *
Marko Mikulicic 0:c0ecb8bf28eb 23922 * See comment for v7->line_no in core.h for some details.
Marko Mikulicic 0:c0ecb8bf28eb 23923 */
Marko Mikulicic 0:c0ecb8bf28eb 23924 v7->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23925
Marko Mikulicic 0:c0ecb8bf28eb 23926 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23927 /*
Marko Mikulicic 0:c0ecb8bf28eb 23928 * setup initial state for "after newline" tracking.
Marko Mikulicic 0:c0ecb8bf28eb 23929 * next_tok will consume our token and position the current line
Marko Mikulicic 0:c0ecb8bf28eb 23930 * position at the beginning of the next token.
Marko Mikulicic 0:c0ecb8bf28eb 23931 * While processing the first token, both the leading and the
Marko Mikulicic 0:c0ecb8bf28eb 23932 * trailing newlines will be counted and thus it will create a spurious
Marko Mikulicic 0:c0ecb8bf28eb 23933 * "after newline" condition at the end of the first token
Marko Mikulicic 0:c0ecb8bf28eb 23934 * regardless if there is actually a newline after it.
Marko Mikulicic 0:c0ecb8bf28eb 23935 */
Marko Mikulicic 0:c0ecb8bf28eb 23936 for (p = src; isspace((int) *p); p++) {
Marko Mikulicic 0:c0ecb8bf28eb 23937 if (*p == '\n') {
Marko Mikulicic 0:c0ecb8bf28eb 23938 v7->pstate.prev_line_no++;
Marko Mikulicic 0:c0ecb8bf28eb 23939 }
Marko Mikulicic 0:c0ecb8bf28eb 23940 }
Marko Mikulicic 0:c0ecb8bf28eb 23941
Marko Mikulicic 0:c0ecb8bf28eb 23942 /* init cr context */
Marko Mikulicic 0:c0ecb8bf28eb 23943 cr_context_init(&cr_ctx, &arg_retval, sizeof(arg_retval), _fid_descrs);
Marko Mikulicic 0:c0ecb8bf28eb 23944
Marko Mikulicic 0:c0ecb8bf28eb 23945 /* prepare first function call: fid_mul_sum */
Marko Mikulicic 0:c0ecb8bf28eb 23946 if (is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 23947 CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_terminal);
Marko Mikulicic 0:c0ecb8bf28eb 23948 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23949 CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_script);
Marko Mikulicic 0:c0ecb8bf28eb 23950 }
Marko Mikulicic 0:c0ecb8bf28eb 23951
Marko Mikulicic 0:c0ecb8bf28eb 23952 /* proceed to coroutine execution */
Marko Mikulicic 0:c0ecb8bf28eb 23953 rc = parser_cr_exec(&cr_ctx, v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 23954
Marko Mikulicic 0:c0ecb8bf28eb 23955 /* set `rcode` depending on coroutine state */
Marko Mikulicic 0:c0ecb8bf28eb 23956 switch (rc) {
Marko Mikulicic 0:c0ecb8bf28eb 23957 case CR_RES__OK:
Marko Mikulicic 0:c0ecb8bf28eb 23958 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 23959 break;
Marko Mikulicic 0:c0ecb8bf28eb 23960 case CR_RES__ERR_UNCAUGHT_EXCEPTION:
Marko Mikulicic 0:c0ecb8bf28eb 23961 switch ((enum parser_exc_id) CR_THROWN_C(&cr_ctx)) {
Marko Mikulicic 0:c0ecb8bf28eb 23962 case PARSER_EXC_ID__SYNTAX_ERROR:
Marko Mikulicic 0:c0ecb8bf28eb 23963 rcode = V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 23964 error_msg = "Syntax error";
Marko Mikulicic 0:c0ecb8bf28eb 23965 break;
Marko Mikulicic 0:c0ecb8bf28eb 23966
Marko Mikulicic 0:c0ecb8bf28eb 23967 default:
Marko Mikulicic 0:c0ecb8bf28eb 23968 rcode = V7_INTERNAL_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 23969 error_msg = "Internal error: no exception id set";
Marko Mikulicic 0:c0ecb8bf28eb 23970 break;
Marko Mikulicic 0:c0ecb8bf28eb 23971 }
Marko Mikulicic 0:c0ecb8bf28eb 23972 break;
Marko Mikulicic 0:c0ecb8bf28eb 23973 default:
Marko Mikulicic 0:c0ecb8bf28eb 23974 rcode = V7_INTERNAL_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 23975 error_msg = "Internal error: unexpected parser coroutine return code";
Marko Mikulicic 0:c0ecb8bf28eb 23976 break;
Marko Mikulicic 0:c0ecb8bf28eb 23977 }
Marko Mikulicic 0:c0ecb8bf28eb 23978
Marko Mikulicic 0:c0ecb8bf28eb 23979 #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 23980 /* remember how much stack space was consumed */
Marko Mikulicic 0:c0ecb8bf28eb 23981
Marko Mikulicic 0:c0ecb8bf28eb 23982 if (v7->parser_stack_data_max_size < cr_ctx.stack_data.size) {
Marko Mikulicic 0:c0ecb8bf28eb 23983 v7->parser_stack_data_max_size = cr_ctx.stack_data.size;
Marko Mikulicic 0:c0ecb8bf28eb 23984 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 23985 printf("parser_stack_data_max_size=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 23986 (unsigned int) v7->parser_stack_data_max_size);
Marko Mikulicic 0:c0ecb8bf28eb 23987 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23988 }
Marko Mikulicic 0:c0ecb8bf28eb 23989
Marko Mikulicic 0:c0ecb8bf28eb 23990 if (v7->parser_stack_ret_max_size < cr_ctx.stack_ret.size) {
Marko Mikulicic 0:c0ecb8bf28eb 23991 v7->parser_stack_ret_max_size = cr_ctx.stack_ret.size;
Marko Mikulicic 0:c0ecb8bf28eb 23992 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 23993 printf("parser_stack_ret_max_size=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 23994 (unsigned int) v7->parser_stack_ret_max_size);
Marko Mikulicic 0:c0ecb8bf28eb 23995 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23996 }
Marko Mikulicic 0:c0ecb8bf28eb 23997
Marko Mikulicic 0:c0ecb8bf28eb 23998 #if defined(CR_TRACK_MAX_STACK_LEN)
Marko Mikulicic 0:c0ecb8bf28eb 23999 if (v7->parser_stack_data_max_len < cr_ctx.stack_data_max_len) {
Marko Mikulicic 0:c0ecb8bf28eb 24000 v7->parser_stack_data_max_len = cr_ctx.stack_data_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 24001 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 24002 printf("parser_stack_data_max_len=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 24003 (unsigned int) v7->parser_stack_data_max_len);
Marko Mikulicic 0:c0ecb8bf28eb 24004 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24005 }
Marko Mikulicic 0:c0ecb8bf28eb 24006
Marko Mikulicic 0:c0ecb8bf28eb 24007 if (v7->parser_stack_ret_max_len < cr_ctx.stack_ret_max_len) {
Marko Mikulicic 0:c0ecb8bf28eb 24008 v7->parser_stack_ret_max_len = cr_ctx.stack_ret_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 24009 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 24010 printf("parser_stack_ret_max_len=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 24011 (unsigned int) v7->parser_stack_ret_max_len);
Marko Mikulicic 0:c0ecb8bf28eb 24012 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24013 }
Marko Mikulicic 0:c0ecb8bf28eb 24014 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24015
Marko Mikulicic 0:c0ecb8bf28eb 24016 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24017
Marko Mikulicic 0:c0ecb8bf28eb 24018 /* free resources occupied by context (at least, "stack" arrays) */
Marko Mikulicic 0:c0ecb8bf28eb 24019 cr_context_free(&cr_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 24020
Marko Mikulicic 0:c0ecb8bf28eb 24021 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 24022 {
Marko Mikulicic 0:c0ecb8bf28eb 24023 int diff = v7_stack_track_end(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 24024 if (diff > v7->stack_stat[V7_STACK_STAT_PARSER]) {
Marko Mikulicic 0:c0ecb8bf28eb 24025 v7->stack_stat[V7_STACK_STAT_PARSER] = diff;
Marko Mikulicic 0:c0ecb8bf28eb 24026 }
Marko Mikulicic 0:c0ecb8bf28eb 24027 }
Marko Mikulicic 0:c0ecb8bf28eb 24028 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24029
Marko Mikulicic 0:c0ecb8bf28eb 24030 /* Check if AST was overflown */
Marko Mikulicic 0:c0ecb8bf28eb 24031 if (a->has_overflow) {
Marko Mikulicic 0:c0ecb8bf28eb 24032 rcode = v7_throwf(v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 24033 "Script too large (try V7_LARGE_AST build option)");
Marko Mikulicic 0:c0ecb8bf28eb 24034 V7_THROW(V7_AST_TOO_LARGE);
Marko Mikulicic 0:c0ecb8bf28eb 24035 }
Marko Mikulicic 0:c0ecb8bf28eb 24036
Marko Mikulicic 0:c0ecb8bf28eb 24037 if (rcode == V7_OK && v7->cur_tok != TOK_END_OF_INPUT) {
Marko Mikulicic 0:c0ecb8bf28eb 24038 rcode = V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 24039 error_msg = "Syntax error";
Marko Mikulicic 0:c0ecb8bf28eb 24040 }
Marko Mikulicic 0:c0ecb8bf28eb 24041
Marko Mikulicic 0:c0ecb8bf28eb 24042 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 24043 unsigned long col = get_column(v7->pstate.source_code, v7->tok);
Marko Mikulicic 0:c0ecb8bf28eb 24044 int line_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 24045
Marko Mikulicic 0:c0ecb8bf28eb 24046 assert(error_msg != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 24047
Marko Mikulicic 0:c0ecb8bf28eb 24048 for (p = v7->tok - col; p < v7->pstate.src_end && *p != '\0' && *p != '\n';
Marko Mikulicic 0:c0ecb8bf28eb 24049 p++) {
Marko Mikulicic 0:c0ecb8bf28eb 24050 line_len++;
Marko Mikulicic 0:c0ecb8bf28eb 24051 }
Marko Mikulicic 0:c0ecb8bf28eb 24052
Marko Mikulicic 0:c0ecb8bf28eb 24053 /* fixup line number: line_no points to the beginning of the next token */
Marko Mikulicic 0:c0ecb8bf28eb 24054 for (; p < v7->pstate.pc; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 24055 if (*p == '\n') {
Marko Mikulicic 0:c0ecb8bf28eb 24056 v7->pstate.line_no--;
Marko Mikulicic 0:c0ecb8bf28eb 24057 }
Marko Mikulicic 0:c0ecb8bf28eb 24058 }
Marko Mikulicic 0:c0ecb8bf28eb 24059
Marko Mikulicic 0:c0ecb8bf28eb 24060 /*
Marko Mikulicic 0:c0ecb8bf28eb 24061 * We already have a proper `rcode`, that's why we discard returned value
Marko Mikulicic 0:c0ecb8bf28eb 24062 * of `v7_throwf()`, which is always `V7_EXEC_EXCEPTION`.
Marko Mikulicic 0:c0ecb8bf28eb 24063 *
Marko Mikulicic 0:c0ecb8bf28eb 24064 * TODO(dfrank): probably get rid of distinct error types, and use just
Marko Mikulicic 0:c0ecb8bf28eb 24065 * `V7_JS_EXCEPTION`. However it would be good to have a way to get exact
Marko Mikulicic 0:c0ecb8bf28eb 24066 * error type, so probably error object should contain some property with
Marko Mikulicic 0:c0ecb8bf28eb 24067 * error code, but it would make exceptions even more expensive, etc, etc.
Marko Mikulicic 0:c0ecb8bf28eb 24068 */
Marko Mikulicic 0:c0ecb8bf28eb 24069 {
Marko Mikulicic 0:c0ecb8bf28eb 24070 enum v7_err _tmp;
Marko Mikulicic 0:c0ecb8bf28eb 24071 _tmp = v7_throwf(v7, SYNTAX_ERROR, "%s at line %d col %lu:\n%.*s\n%*s^",
Marko Mikulicic 0:c0ecb8bf28eb 24072 error_msg, v7->pstate.line_no, col, line_len,
Marko Mikulicic 0:c0ecb8bf28eb 24073 v7->tok - col, (int) col - 1, "");
Marko Mikulicic 0:c0ecb8bf28eb 24074 (void) _tmp;
Marko Mikulicic 0:c0ecb8bf28eb 24075 }
Marko Mikulicic 0:c0ecb8bf28eb 24076 V7_THROW(rcode);
Marko Mikulicic 0:c0ecb8bf28eb 24077 }
Marko Mikulicic 0:c0ecb8bf28eb 24078
Marko Mikulicic 0:c0ecb8bf28eb 24079 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24080 v7->line_no = saved_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 24081 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24082 }
Marko Mikulicic 0:c0ecb8bf28eb 24083
Marko Mikulicic 0:c0ecb8bf28eb 24084 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 24085 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 24086 #line 1 "v7/src/compiler.c"
Marko Mikulicic 0:c0ecb8bf28eb 24087 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24088 /*
Marko Mikulicic 0:c0ecb8bf28eb 24089 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 24090 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 24091 */
Marko Mikulicic 0:c0ecb8bf28eb 24092
Marko Mikulicic 0:c0ecb8bf28eb 24093 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24094 /* Amalgamated: #include "v7/src/compiler.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24095 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24096 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24097 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24098 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24099 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24100 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24101
Marko Mikulicic 0:c0ecb8bf28eb 24102 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 24103
Marko Mikulicic 0:c0ecb8bf28eb 24104 /*
Marko Mikulicic 0:c0ecb8bf28eb 24105 * The bytecode compiler takes an AST as input and produces one or more
Marko Mikulicic 0:c0ecb8bf28eb 24106 * bcode structure as output.
Marko Mikulicic 0:c0ecb8bf28eb 24107 *
Marko Mikulicic 0:c0ecb8bf28eb 24108 * Each script or function body is compiled into it's own bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 24109 *
Marko Mikulicic 0:c0ecb8bf28eb 24110 * Each bcode stream produces a new value on the stack, i.e. its overall
Marko Mikulicic 0:c0ecb8bf28eb 24111 * stack diagram is: `( -- a)`
Marko Mikulicic 0:c0ecb8bf28eb 24112 *
Marko Mikulicic 0:c0ecb8bf28eb 24113 * This value will be then popped by the function caller or by v7_exec in case
Marko Mikulicic 0:c0ecb8bf28eb 24114 * of scripts.
Marko Mikulicic 0:c0ecb8bf28eb 24115 *
Marko Mikulicic 0:c0ecb8bf28eb 24116 * In JS, the value of a script is the value of the last statement.
Marko Mikulicic 0:c0ecb8bf28eb 24117 * A script with no statement has an `undefined` value.
Marko Mikulicic 0:c0ecb8bf28eb 24118 * Functions instead require an explicit return value, so this matters only
Marko Mikulicic 0:c0ecb8bf28eb 24119 * for `v7_exec` and JS `eval`.
Marko Mikulicic 0:c0ecb8bf28eb 24120 *
Marko Mikulicic 0:c0ecb8bf28eb 24121 * Since an empty script has an undefined value, and each script has to
Marko Mikulicic 0:c0ecb8bf28eb 24122 * yield a value, the script/function prologue consists of a PUSH_UNDEFINED.
Marko Mikulicic 0:c0ecb8bf28eb 24123 *
Marko Mikulicic 0:c0ecb8bf28eb 24124 * Each statement will be compiled to push a value on the stack.
Marko Mikulicic 0:c0ecb8bf28eb 24125 * When a statement begins evaluating, the current TOS is thus either
Marko Mikulicic 0:c0ecb8bf28eb 24126 * the value of the previous statement or `undefined` in case of the first
Marko Mikulicic 0:c0ecb8bf28eb 24127 * statement.
Marko Mikulicic 0:c0ecb8bf28eb 24128 *
Marko Mikulicic 0:c0ecb8bf28eb 24129 * Every statement of a given script/function body always evaluates at the same
Marko Mikulicic 0:c0ecb8bf28eb 24130 * stack depth.
Marko Mikulicic 0:c0ecb8bf28eb 24131 *
Marko Mikulicic 0:c0ecb8bf28eb 24132 * In order to achieve that, after a statement is compiled out, a SWAP_DROP
Marko Mikulicic 0:c0ecb8bf28eb 24133 * opcode is emitted, that drops the value of the previous statement (or the
Marko Mikulicic 0:c0ecb8bf28eb 24134 * initial `undefined`). Dropping the value after the next statement is
Marko Mikulicic 0:c0ecb8bf28eb 24135 * evaluated and not before has allows us to correctly implement exception
Marko Mikulicic 0:c0ecb8bf28eb 24136 * behaviour and the break statement.
Marko Mikulicic 0:c0ecb8bf28eb 24137 *
Marko Mikulicic 0:c0ecb8bf28eb 24138 * Compound statements are constructs such as `if`/`while`/`for`/`try`. These
Marko Mikulicic 0:c0ecb8bf28eb 24139 * constructs contain a body consisting of a possibly empty statement list.
Marko Mikulicic 0:c0ecb8bf28eb 24140 *
Marko Mikulicic 0:c0ecb8bf28eb 24141 * Unlike normal statements, compound statements don't produce a value
Marko Mikulicic 0:c0ecb8bf28eb 24142 * themselves. Their value is either the value of their last executed statement
Marko Mikulicic 0:c0ecb8bf28eb 24143 * in their body, or the previous statement in case their body is empty or not
Marko Mikulicic 0:c0ecb8bf28eb 24144 * evaluated at all.
Marko Mikulicic 0:c0ecb8bf28eb 24145 *
Marko Mikulicic 0:c0ecb8bf28eb 24146 * An example is:
Marko Mikulicic 0:c0ecb8bf28eb 24147 *
Marko Mikulicic 0:c0ecb8bf28eb 24148 * [source,js]
Marko Mikulicic 0:c0ecb8bf28eb 24149 * ----
Marko Mikulicic 0:c0ecb8bf28eb 24150 * try {
Marko Mikulicic 0:c0ecb8bf28eb 24151 * 42;
Marko Mikulicic 0:c0ecb8bf28eb 24152 * someUnexistingVariable;
Marko Mikulicic 0:c0ecb8bf28eb 24153 * } catch(e) {
Marko Mikulicic 0:c0ecb8bf28eb 24154 * while(true) {}
Marko Mikulicic 0:c0ecb8bf28eb 24155 * if(true) {
Marko Mikulicic 0:c0ecb8bf28eb 24156 * }
Marko Mikulicic 0:c0ecb8bf28eb 24157 * if(false) {
Marko Mikulicic 0:c0ecb8bf28eb 24158 * 2;
Marko Mikulicic 0:c0ecb8bf28eb 24159 * }
Marko Mikulicic 0:c0ecb8bf28eb 24160 * break;
Marko Mikulicic 0:c0ecb8bf28eb 24161 * }
Marko Mikulicic 0:c0ecb8bf28eb 24162 * }
Marko Mikulicic 0:c0ecb8bf28eb 24163 * ----
Marko Mikulicic 0:c0ecb8bf28eb 24164 */
Marko Mikulicic 0:c0ecb8bf28eb 24165
Marko Mikulicic 0:c0ecb8bf28eb 24166 static const enum ast_tag assign_ast_map[] = {
Marko Mikulicic 0:c0ecb8bf28eb 24167 AST_REM, AST_MUL, AST_DIV, AST_XOR, AST_ADD, AST_SUB,
Marko Mikulicic 0:c0ecb8bf28eb 24168 AST_OR, AST_AND, AST_LSHIFT, AST_RSHIFT, AST_URSHIFT};
Marko Mikulicic 0:c0ecb8bf28eb 24169
Marko Mikulicic 0:c0ecb8bf28eb 24170 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 24171 extern void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 24172 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24173
Marko Mikulicic 0:c0ecb8bf28eb 24174 V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24175 struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24176
Marko Mikulicic 0:c0ecb8bf28eb 24177 V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24178 ast_off_t *ppos, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 24179
Marko Mikulicic 0:c0ecb8bf28eb 24180 V7_PRIVATE enum v7_err binary_op(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24181 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24182 uint8_t op;
Marko Mikulicic 0:c0ecb8bf28eb 24183 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24184 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24185
Marko Mikulicic 0:c0ecb8bf28eb 24186 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24187 case AST_ADD:
Marko Mikulicic 0:c0ecb8bf28eb 24188 op = OP_ADD;
Marko Mikulicic 0:c0ecb8bf28eb 24189 break;
Marko Mikulicic 0:c0ecb8bf28eb 24190 case AST_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 24191 op = OP_SUB;
Marko Mikulicic 0:c0ecb8bf28eb 24192 break;
Marko Mikulicic 0:c0ecb8bf28eb 24193 case AST_REM:
Marko Mikulicic 0:c0ecb8bf28eb 24194 op = OP_REM;
Marko Mikulicic 0:c0ecb8bf28eb 24195 break;
Marko Mikulicic 0:c0ecb8bf28eb 24196 case AST_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 24197 op = OP_MUL;
Marko Mikulicic 0:c0ecb8bf28eb 24198 break;
Marko Mikulicic 0:c0ecb8bf28eb 24199 case AST_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 24200 op = OP_DIV;
Marko Mikulicic 0:c0ecb8bf28eb 24201 break;
Marko Mikulicic 0:c0ecb8bf28eb 24202 case AST_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24203 op = OP_LSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 24204 break;
Marko Mikulicic 0:c0ecb8bf28eb 24205 case AST_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24206 op = OP_RSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 24207 break;
Marko Mikulicic 0:c0ecb8bf28eb 24208 case AST_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24209 op = OP_URSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 24210 break;
Marko Mikulicic 0:c0ecb8bf28eb 24211 case AST_OR:
Marko Mikulicic 0:c0ecb8bf28eb 24212 op = OP_OR;
Marko Mikulicic 0:c0ecb8bf28eb 24213 break;
Marko Mikulicic 0:c0ecb8bf28eb 24214 case AST_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 24215 op = OP_XOR;
Marko Mikulicic 0:c0ecb8bf28eb 24216 break;
Marko Mikulicic 0:c0ecb8bf28eb 24217 case AST_AND:
Marko Mikulicic 0:c0ecb8bf28eb 24218 op = OP_AND;
Marko Mikulicic 0:c0ecb8bf28eb 24219 break;
Marko Mikulicic 0:c0ecb8bf28eb 24220 case AST_EQ_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24221 op = OP_EQ_EQ;
Marko Mikulicic 0:c0ecb8bf28eb 24222 break;
Marko Mikulicic 0:c0ecb8bf28eb 24223 case AST_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24224 op = OP_EQ;
Marko Mikulicic 0:c0ecb8bf28eb 24225 break;
Marko Mikulicic 0:c0ecb8bf28eb 24226 case AST_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24227 op = OP_NE;
Marko Mikulicic 0:c0ecb8bf28eb 24228 break;
Marko Mikulicic 0:c0ecb8bf28eb 24229 case AST_NE_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24230 op = OP_NE_NE;
Marko Mikulicic 0:c0ecb8bf28eb 24231 break;
Marko Mikulicic 0:c0ecb8bf28eb 24232 case AST_LT:
Marko Mikulicic 0:c0ecb8bf28eb 24233 op = OP_LT;
Marko Mikulicic 0:c0ecb8bf28eb 24234 break;
Marko Mikulicic 0:c0ecb8bf28eb 24235 case AST_LE:
Marko Mikulicic 0:c0ecb8bf28eb 24236 op = OP_LE;
Marko Mikulicic 0:c0ecb8bf28eb 24237 break;
Marko Mikulicic 0:c0ecb8bf28eb 24238 case AST_GT:
Marko Mikulicic 0:c0ecb8bf28eb 24239 op = OP_GT;
Marko Mikulicic 0:c0ecb8bf28eb 24240 break;
Marko Mikulicic 0:c0ecb8bf28eb 24241 case AST_GE:
Marko Mikulicic 0:c0ecb8bf28eb 24242 op = OP_GE;
Marko Mikulicic 0:c0ecb8bf28eb 24243 break;
Marko Mikulicic 0:c0ecb8bf28eb 24244 case AST_INSTANCEOF:
Marko Mikulicic 0:c0ecb8bf28eb 24245 op = OP_INSTANCEOF;
Marko Mikulicic 0:c0ecb8bf28eb 24246 break;
Marko Mikulicic 0:c0ecb8bf28eb 24247 default:
Marko Mikulicic 0:c0ecb8bf28eb 24248 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown binary ast node");
Marko Mikulicic 0:c0ecb8bf28eb 24249 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24250 }
Marko Mikulicic 0:c0ecb8bf28eb 24251 bcode_op(bbuilder, op);
Marko Mikulicic 0:c0ecb8bf28eb 24252 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24253 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24254 }
Marko Mikulicic 0:c0ecb8bf28eb 24255
Marko Mikulicic 0:c0ecb8bf28eb 24256 V7_PRIVATE enum v7_err compile_binary(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24257 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24258 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24259 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24260 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24261 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24262 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24263
Marko Mikulicic 0:c0ecb8bf28eb 24264 V7_TRY(binary_op(bbuilder, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24265 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24266 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24267 }
Marko Mikulicic 0:c0ecb8bf28eb 24268
Marko Mikulicic 0:c0ecb8bf28eb 24269 /*
Marko Mikulicic 0:c0ecb8bf28eb 24270 * `pos` should be an offset of the byte right after a tag
Marko Mikulicic 0:c0ecb8bf28eb 24271 */
Marko Mikulicic 0:c0ecb8bf28eb 24272 static lit_t string_lit(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24273 ast_off_t pos) {
Marko Mikulicic 0:c0ecb8bf28eb 24274 size_t i = 0, name_len;
Marko Mikulicic 0:c0ecb8bf28eb 24275 val_t v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 24276 struct mbuf *m = &bbuilder->lit;
Marko Mikulicic 0:c0ecb8bf28eb 24277 char *name = ast_get_inlined_data(a, pos, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 24278
Marko Mikulicic 0:c0ecb8bf28eb 24279 /* temp disabled because of short lits */
Marko Mikulicic 0:c0ecb8bf28eb 24280 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 24281 for (i = 0; i < m->len / sizeof(val_t); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 24282 v = ((val_t *) m->buf)[i];
Marko Mikulicic 0:c0ecb8bf28eb 24283 if (v7_is_string(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 24284 size_t l;
Marko Mikulicic 0:c0ecb8bf28eb 24285 const char *s = v7_get_string(bbuilder->v7, &v, &l);
Marko Mikulicic 0:c0ecb8bf28eb 24286 if (name_len == l && memcmp(name, s, name_len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 24287 lit_t res;
Marko Mikulicic 0:c0ecb8bf28eb 24288 memset(&res, 0, sizeof(res));
Marko Mikulicic 0:c0ecb8bf28eb 24289 res.idx = i + bcode_max_inline_type_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24290 return res;
Marko Mikulicic 0:c0ecb8bf28eb 24291 }
Marko Mikulicic 0:c0ecb8bf28eb 24292 }
Marko Mikulicic 0:c0ecb8bf28eb 24293 }
Marko Mikulicic 0:c0ecb8bf28eb 24294 #else
Marko Mikulicic 0:c0ecb8bf28eb 24295 (void) i;
Marko Mikulicic 0:c0ecb8bf28eb 24296 (void) v;
Marko Mikulicic 0:c0ecb8bf28eb 24297 (void) m;
Marko Mikulicic 0:c0ecb8bf28eb 24298 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24299 return bcode_add_lit(bbuilder, v7_mk_string(bbuilder->v7, name, name_len, 1));
Marko Mikulicic 0:c0ecb8bf28eb 24300 }
Marko Mikulicic 0:c0ecb8bf28eb 24301
Marko Mikulicic 0:c0ecb8bf28eb 24302 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 24303 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 24304 static enum v7_err regexp_lit(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24305 ast_off_t pos, lit_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 24306 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24307 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 24308 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 24309 char *name = ast_get_inlined_data(a, pos, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 24310 val_t tmp = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 24311 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24312
Marko Mikulicic 0:c0ecb8bf28eb 24313 for (p = name + name_len - 1; *p != '/';) p--;
Marko Mikulicic 0:c0ecb8bf28eb 24314
Marko Mikulicic 0:c0ecb8bf28eb 24315 V7_TRY(v7_mk_regexp(bbuilder->v7, name + 1, p - (name + 1), p + 1,
Marko Mikulicic 0:c0ecb8bf28eb 24316 (name + name_len) - p - 1, &tmp));
Marko Mikulicic 0:c0ecb8bf28eb 24317
Marko Mikulicic 0:c0ecb8bf28eb 24318 *res = bcode_add_lit(bbuilder, tmp);
Marko Mikulicic 0:c0ecb8bf28eb 24319
Marko Mikulicic 0:c0ecb8bf28eb 24320 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24321 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24322 }
Marko Mikulicic 0:c0ecb8bf28eb 24323 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24324
Marko Mikulicic 0:c0ecb8bf28eb 24325 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 24326 static void append_lineno_if_changed(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 24327 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24328 int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 24329 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 24330 if (line_no != 0 && line_no != v7->line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 24331 v7->line_no = line_no;
Marko Mikulicic 0:c0ecb8bf28eb 24332 bcode_append_lineno(bbuilder, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 24333 }
Marko Mikulicic 0:c0ecb8bf28eb 24334 }
Marko Mikulicic 0:c0ecb8bf28eb 24335 #else
Marko Mikulicic 0:c0ecb8bf28eb 24336 static void append_lineno_if_changed(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 24337 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24338 int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 24339 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 24340 (void) bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 24341 (void) line_no;
Marko Mikulicic 0:c0ecb8bf28eb 24342 }
Marko Mikulicic 0:c0ecb8bf28eb 24343 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24344
Marko Mikulicic 0:c0ecb8bf28eb 24345 static enum ast_tag fetch_tag(struct v7 *v7, struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24346 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24347 ast_off_t *ppos_after_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24348 enum ast_tag ret = ast_fetch_tag(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24349 int line_no = ast_get_line_no(a, *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24350 append_lineno_if_changed(v7, bbuilder, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 24351 if (ppos_after_tag != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 24352 *ppos_after_tag = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 24353 }
Marko Mikulicic 0:c0ecb8bf28eb 24354 ast_move_to_children(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24355 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 24356 }
Marko Mikulicic 0:c0ecb8bf28eb 24357
Marko Mikulicic 0:c0ecb8bf28eb 24358 /*
Marko Mikulicic 0:c0ecb8bf28eb 24359 * a++ and a-- need to ignore the updated value.
Marko Mikulicic 0:c0ecb8bf28eb 24360 *
Marko Mikulicic 0:c0ecb8bf28eb 24361 * Call this before updating the lhs.
Marko Mikulicic 0:c0ecb8bf28eb 24362 */
Marko Mikulicic 0:c0ecb8bf28eb 24363 static void fixup_post_op(struct bcode_builder *bbuilder, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24364 if (tag == AST_POSTINC || tag == AST_POSTDEC) {
Marko Mikulicic 0:c0ecb8bf28eb 24365 bcode_op(bbuilder, OP_UNSTASH);
Marko Mikulicic 0:c0ecb8bf28eb 24366 }
Marko Mikulicic 0:c0ecb8bf28eb 24367 }
Marko Mikulicic 0:c0ecb8bf28eb 24368
Marko Mikulicic 0:c0ecb8bf28eb 24369 /*
Marko Mikulicic 0:c0ecb8bf28eb 24370 * evaluate rhs expression.
Marko Mikulicic 0:c0ecb8bf28eb 24371 * ++a and a++ are equivalent to a+=1
Marko Mikulicic 0:c0ecb8bf28eb 24372 */
Marko Mikulicic 0:c0ecb8bf28eb 24373 static enum v7_err eval_assign_rhs(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24374 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24375 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24376 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24377 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24378
Marko Mikulicic 0:c0ecb8bf28eb 24379 /* a++ and a-- need to preserve initial value. */
Marko Mikulicic 0:c0ecb8bf28eb 24380 if (tag == AST_POSTINC || tag == AST_POSTDEC) {
Marko Mikulicic 0:c0ecb8bf28eb 24381 bcode_op(bbuilder, OP_STASH);
Marko Mikulicic 0:c0ecb8bf28eb 24382 }
Marko Mikulicic 0:c0ecb8bf28eb 24383 if (tag >= AST_PREINC && tag <= AST_POSTDEC) {
Marko Mikulicic 0:c0ecb8bf28eb 24384 bcode_op(bbuilder, OP_PUSH_ONE);
Marko Mikulicic 0:c0ecb8bf28eb 24385 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24386 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24387 }
Marko Mikulicic 0:c0ecb8bf28eb 24388
Marko Mikulicic 0:c0ecb8bf28eb 24389 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24390 case AST_PREINC:
Marko Mikulicic 0:c0ecb8bf28eb 24391 case AST_POSTINC:
Marko Mikulicic 0:c0ecb8bf28eb 24392 bcode_op(bbuilder, OP_ADD);
Marko Mikulicic 0:c0ecb8bf28eb 24393 break;
Marko Mikulicic 0:c0ecb8bf28eb 24394 case AST_PREDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24395 case AST_POSTDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24396 bcode_op(bbuilder, OP_SUB);
Marko Mikulicic 0:c0ecb8bf28eb 24397 break;
Marko Mikulicic 0:c0ecb8bf28eb 24398 case AST_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24399 /* no operation */
Marko Mikulicic 0:c0ecb8bf28eb 24400 break;
Marko Mikulicic 0:c0ecb8bf28eb 24401 default:
Marko Mikulicic 0:c0ecb8bf28eb 24402 binary_op(bbuilder, assign_ast_map[tag - AST_ASSIGN - 1]);
Marko Mikulicic 0:c0ecb8bf28eb 24403 }
Marko Mikulicic 0:c0ecb8bf28eb 24404
Marko Mikulicic 0:c0ecb8bf28eb 24405 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24406 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24407 }
Marko Mikulicic 0:c0ecb8bf28eb 24408
Marko Mikulicic 0:c0ecb8bf28eb 24409 static enum v7_err compile_assign(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24410 ast_off_t *ppos, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24411 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 24412 enum ast_tag ntag;
Marko Mikulicic 0:c0ecb8bf28eb 24413 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24414 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24415 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24416
Marko Mikulicic 0:c0ecb8bf28eb 24417 ntag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24418
Marko Mikulicic 0:c0ecb8bf28eb 24419 switch (ntag) {
Marko Mikulicic 0:c0ecb8bf28eb 24420 case AST_IDENT:
Marko Mikulicic 0:c0ecb8bf28eb 24421 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24422 if (tag != AST_ASSIGN) {
Marko Mikulicic 0:c0ecb8bf28eb 24423 bcode_op_lit(bbuilder, OP_GET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24424 }
Marko Mikulicic 0:c0ecb8bf28eb 24425
Marko Mikulicic 0:c0ecb8bf28eb 24426 V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24427 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24428
Marko Mikulicic 0:c0ecb8bf28eb 24429 fixup_post_op(bbuilder, tag);
Marko Mikulicic 0:c0ecb8bf28eb 24430 break;
Marko Mikulicic 0:c0ecb8bf28eb 24431 case AST_MEMBER:
Marko Mikulicic 0:c0ecb8bf28eb 24432 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24433 switch (ntag) {
Marko Mikulicic 0:c0ecb8bf28eb 24434 case AST_MEMBER:
Marko Mikulicic 0:c0ecb8bf28eb 24435 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24436 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24437 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24438 break;
Marko Mikulicic 0:c0ecb8bf28eb 24439 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24440 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24441 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24442 break;
Marko Mikulicic 0:c0ecb8bf28eb 24443 default:
Marko Mikulicic 0:c0ecb8bf28eb 24444 /* unreachable, compilers are dumb */
Marko Mikulicic 0:c0ecb8bf28eb 24445 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24446 }
Marko Mikulicic 0:c0ecb8bf28eb 24447 if (tag != AST_ASSIGN) {
Marko Mikulicic 0:c0ecb8bf28eb 24448 bcode_op(bbuilder, OP_2DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24449 bcode_op(bbuilder, OP_GET);
Marko Mikulicic 0:c0ecb8bf28eb 24450 }
Marko Mikulicic 0:c0ecb8bf28eb 24451
Marko Mikulicic 0:c0ecb8bf28eb 24452 V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24453 bcode_op(bbuilder, OP_SET);
Marko Mikulicic 0:c0ecb8bf28eb 24454
Marko Mikulicic 0:c0ecb8bf28eb 24455 fixup_post_op(bbuilder, tag);
Marko Mikulicic 0:c0ecb8bf28eb 24456 break;
Marko Mikulicic 0:c0ecb8bf28eb 24457 default:
Marko Mikulicic 0:c0ecb8bf28eb 24458 /* We end up here on expressions like `1 = 2;`, it's a ReferenceError */
Marko Mikulicic 0:c0ecb8bf28eb 24459 rcode = v7_throwf(bbuilder->v7, REFERENCE_ERROR, "unexpected ast node");
Marko Mikulicic 0:c0ecb8bf28eb 24460 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24461 }
Marko Mikulicic 0:c0ecb8bf28eb 24462 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24463 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24464 }
Marko Mikulicic 0:c0ecb8bf28eb 24465
Marko Mikulicic 0:c0ecb8bf28eb 24466 /*
Marko Mikulicic 0:c0ecb8bf28eb 24467 * Walks through all declarations (`var` and `function`) in the current scope,
Marko Mikulicic 0:c0ecb8bf28eb 24468 * and adds names of all of them to `bcode->ops`. Additionally, `function`
Marko Mikulicic 0:c0ecb8bf28eb 24469 * declarations are compiled right here, since they're hoisted in JS.
Marko Mikulicic 0:c0ecb8bf28eb 24470 */
Marko Mikulicic 0:c0ecb8bf28eb 24471 static enum v7_err compile_local_vars(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24472 struct ast *a, ast_off_t start,
Marko Mikulicic 0:c0ecb8bf28eb 24473 ast_off_t fvar) {
Marko Mikulicic 0:c0ecb8bf28eb 24474 ast_off_t next, fvar_end;
Marko Mikulicic 0:c0ecb8bf28eb 24475 char *name;
Marko Mikulicic 0:c0ecb8bf28eb 24476 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 24477 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 24478 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24479 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24480 size_t names_end = 0;
Marko Mikulicic 0:c0ecb8bf28eb 24481 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24482
Marko Mikulicic 0:c0ecb8bf28eb 24483 /* calculate `names_end`: offset at which names in `bcode->ops` end */
Marko Mikulicic 0:c0ecb8bf28eb 24484 names_end =
Marko Mikulicic 0:c0ecb8bf28eb 24485 (size_t)(bcode_end_names(bbuilder->ops.buf, bbuilder->bcode->names_cnt) -
Marko Mikulicic 0:c0ecb8bf28eb 24486 bbuilder->ops.buf);
Marko Mikulicic 0:c0ecb8bf28eb 24487
Marko Mikulicic 0:c0ecb8bf28eb 24488 if (fvar != start) {
Marko Mikulicic 0:c0ecb8bf28eb 24489 /* iterate all `AST_VAR`s in the current scope */
Marko Mikulicic 0:c0ecb8bf28eb 24490 do {
Marko Mikulicic 0:c0ecb8bf28eb 24491 V7_CHECK_INTERNAL(fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag) ==
Marko Mikulicic 0:c0ecb8bf28eb 24492 AST_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 24493
Marko Mikulicic 0:c0ecb8bf28eb 24494 next = ast_get_skip(a, pos_after_tag, AST_VAR_NEXT_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24495 if (next == pos_after_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24496 next = 0;
Marko Mikulicic 0:c0ecb8bf28eb 24497 }
Marko Mikulicic 0:c0ecb8bf28eb 24498
Marko Mikulicic 0:c0ecb8bf28eb 24499 fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24500
Marko Mikulicic 0:c0ecb8bf28eb 24501 /*
Marko Mikulicic 0:c0ecb8bf28eb 24502 * iterate all `AST_VAR_DECL`s and `AST_FUNC_DECL`s in the current
Marko Mikulicic 0:c0ecb8bf28eb 24503 * `AST_VAR`
Marko Mikulicic 0:c0ecb8bf28eb 24504 */
Marko Mikulicic 0:c0ecb8bf28eb 24505 while (fvar < fvar_end) {
Marko Mikulicic 0:c0ecb8bf28eb 24506 enum ast_tag tag = fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24507 V7_CHECK_INTERNAL(tag == AST_VAR_DECL || tag == AST_FUNC_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 24508 name = ast_get_inlined_data(a, pos_after_tag, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 24509 if (tag == AST_VAR_DECL) {
Marko Mikulicic 0:c0ecb8bf28eb 24510 /*
Marko Mikulicic 0:c0ecb8bf28eb 24511 * it's a `var` declaration, so, skip the value for now, it'll be set
Marko Mikulicic 0:c0ecb8bf28eb 24512 * to `undefined` initially
Marko Mikulicic 0:c0ecb8bf28eb 24513 */
Marko Mikulicic 0:c0ecb8bf28eb 24514 ast_skip_tree(a, &fvar);
Marko Mikulicic 0:c0ecb8bf28eb 24515 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24516 /*
Marko Mikulicic 0:c0ecb8bf28eb 24517 * tag is an AST_FUNC_DECL: since functions in JS are hoisted,
Marko Mikulicic 0:c0ecb8bf28eb 24518 * we compile it and put `OP_SET_VAR` directly here
Marko Mikulicic 0:c0ecb8bf28eb 24519 */
Marko Mikulicic 0:c0ecb8bf28eb 24520 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24521 V7_TRY(compile_expr_builder(bbuilder, a, &fvar));
Marko Mikulicic 0:c0ecb8bf28eb 24522 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24523
Marko Mikulicic 0:c0ecb8bf28eb 24524 /* function declarations are stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 24525 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24526 /*
Marko Mikulicic 0:c0ecb8bf28eb 24527 * Note: the `is_stack_neutral` flag will be set by `compile_stmt`
Marko Mikulicic 0:c0ecb8bf28eb 24528 * later, when it encounters `AST_FUNC_DECL` again.
Marko Mikulicic 0:c0ecb8bf28eb 24529 */
Marko Mikulicic 0:c0ecb8bf28eb 24530 }
Marko Mikulicic 0:c0ecb8bf28eb 24531 V7_TRY(bcode_add_name(bbuilder, name, name_len, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 24532 }
Marko Mikulicic 0:c0ecb8bf28eb 24533
Marko Mikulicic 0:c0ecb8bf28eb 24534 if (next > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 24535 fvar = next - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24536 }
Marko Mikulicic 0:c0ecb8bf28eb 24537
Marko Mikulicic 0:c0ecb8bf28eb 24538 } while (next != 0);
Marko Mikulicic 0:c0ecb8bf28eb 24539 }
Marko Mikulicic 0:c0ecb8bf28eb 24540
Marko Mikulicic 0:c0ecb8bf28eb 24541 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24542 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24543 }
Marko Mikulicic 0:c0ecb8bf28eb 24544
Marko Mikulicic 0:c0ecb8bf28eb 24545 /*
Marko Mikulicic 0:c0ecb8bf28eb 24546 * Just like `compile_expr_builder`, but it takes additional argument:
Marko Mikulicic 0:c0ecb8bf28eb 24547 *`for_call`.
Marko Mikulicic 0:c0ecb8bf28eb 24548 * If it's non-zero, the stack is additionally populated with `this` value
Marko Mikulicic 0:c0ecb8bf28eb 24549 * for call.
Marko Mikulicic 0:c0ecb8bf28eb 24550 *
Marko Mikulicic 0:c0ecb8bf28eb 24551 * If there is a refinement (a dot, or a subscript), then it'll be the
Marko Mikulicic 0:c0ecb8bf28eb 24552 * appropriate object. Otherwise, it's `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 24553 *
Marko Mikulicic 0:c0ecb8bf28eb 24554 * In non-strict mode, `undefined` will be changed to Global Object at runtime,
Marko Mikulicic 0:c0ecb8bf28eb 24555 * see `OP_CALL` handling in `eval_bcode()`.
Marko Mikulicic 0:c0ecb8bf28eb 24556 */
Marko Mikulicic 0:c0ecb8bf28eb 24557 V7_PRIVATE enum v7_err compile_expr_ext(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24558 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24559 uint8_t for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24560 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24561 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24562 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24563 enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24564
Marko Mikulicic 0:c0ecb8bf28eb 24565 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24566 case AST_MEMBER: {
Marko Mikulicic 0:c0ecb8bf28eb 24567 lit_t lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24568 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24569 if (for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24570 /* current TOS will be used as `this` */
Marko Mikulicic 0:c0ecb8bf28eb 24571 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24572 }
Marko Mikulicic 0:c0ecb8bf28eb 24573 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24574 bcode_op(bbuilder, OP_GET);
Marko Mikulicic 0:c0ecb8bf28eb 24575 break;
Marko Mikulicic 0:c0ecb8bf28eb 24576 }
Marko Mikulicic 0:c0ecb8bf28eb 24577
Marko Mikulicic 0:c0ecb8bf28eb 24578 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24579 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24580 if (for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24581 /* current TOS will be used as `this` */
Marko Mikulicic 0:c0ecb8bf28eb 24582 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24583 }
Marko Mikulicic 0:c0ecb8bf28eb 24584 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24585 bcode_op(bbuilder, OP_GET);
Marko Mikulicic 0:c0ecb8bf28eb 24586 break;
Marko Mikulicic 0:c0ecb8bf28eb 24587
Marko Mikulicic 0:c0ecb8bf28eb 24588 default:
Marko Mikulicic 0:c0ecb8bf28eb 24589 if (for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24590 /*
Marko Mikulicic 0:c0ecb8bf28eb 24591 * `this` will be an `undefined` (but it may change to Global Object
Marko Mikulicic 0:c0ecb8bf28eb 24592 * at runtime)
Marko Mikulicic 0:c0ecb8bf28eb 24593 */
Marko Mikulicic 0:c0ecb8bf28eb 24594 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 24595 }
Marko Mikulicic 0:c0ecb8bf28eb 24596 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24597 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24598 break;
Marko Mikulicic 0:c0ecb8bf28eb 24599 }
Marko Mikulicic 0:c0ecb8bf28eb 24600
Marko Mikulicic 0:c0ecb8bf28eb 24601 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24602 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24603 }
Marko Mikulicic 0:c0ecb8bf28eb 24604
Marko Mikulicic 0:c0ecb8bf28eb 24605 V7_PRIVATE enum v7_err compile_delete(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24606 struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 24607 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24608 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24609 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24610 enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24611
Marko Mikulicic 0:c0ecb8bf28eb 24612 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24613 case AST_MEMBER: {
Marko Mikulicic 0:c0ecb8bf28eb 24614 /* Delete a specified property of an object */
Marko Mikulicic 0:c0ecb8bf28eb 24615 lit_t lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24616 /* put an object to delete property from */
Marko Mikulicic 0:c0ecb8bf28eb 24617 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24618 /* put a property name */
Marko Mikulicic 0:c0ecb8bf28eb 24619 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24620 bcode_op(bbuilder, OP_DELETE);
Marko Mikulicic 0:c0ecb8bf28eb 24621 break;
Marko Mikulicic 0:c0ecb8bf28eb 24622 }
Marko Mikulicic 0:c0ecb8bf28eb 24623
Marko Mikulicic 0:c0ecb8bf28eb 24624 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24625 /* Delete a specified property of an object */
Marko Mikulicic 0:c0ecb8bf28eb 24626 /* put an object to delete property from */
Marko Mikulicic 0:c0ecb8bf28eb 24627 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24628 /* put a property name */
Marko Mikulicic 0:c0ecb8bf28eb 24629 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24630 bcode_op(bbuilder, OP_DELETE);
Marko Mikulicic 0:c0ecb8bf28eb 24631 break;
Marko Mikulicic 0:c0ecb8bf28eb 24632
Marko Mikulicic 0:c0ecb8bf28eb 24633 case AST_IDENT:
Marko Mikulicic 0:c0ecb8bf28eb 24634 /* Delete the scope variable (or throw an error if strict mode) */
Marko Mikulicic 0:c0ecb8bf28eb 24635 if (!bbuilder->bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 24636 /* put a property name */
Marko Mikulicic 0:c0ecb8bf28eb 24637 bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 24638 bcode_op(bbuilder, OP_DELETE_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 24639 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24640 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 24641 v7_throwf(bbuilder->v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 24642 "Delete of an unqualified identifier in strict mode.");
Marko Mikulicic 0:c0ecb8bf28eb 24643 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24644 }
Marko Mikulicic 0:c0ecb8bf28eb 24645 break;
Marko Mikulicic 0:c0ecb8bf28eb 24646
Marko Mikulicic 0:c0ecb8bf28eb 24647 case AST_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 24648 /*
Marko Mikulicic 0:c0ecb8bf28eb 24649 * `undefined` should actually be an undeletable property of the Global
Marko Mikulicic 0:c0ecb8bf28eb 24650 * Object, so, trying to delete it just yields `false`
Marko Mikulicic 0:c0ecb8bf28eb 24651 */
Marko Mikulicic 0:c0ecb8bf28eb 24652 bcode_op(bbuilder, OP_PUSH_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 24653 break;
Marko Mikulicic 0:c0ecb8bf28eb 24654
Marko Mikulicic 0:c0ecb8bf28eb 24655 default:
Marko Mikulicic 0:c0ecb8bf28eb 24656 /*
Marko Mikulicic 0:c0ecb8bf28eb 24657 * For all other cases, we evaluate the expression given to `delete`
Marko Mikulicic 0:c0ecb8bf28eb 24658 * for side effects, then drop the result, and yield `true`
Marko Mikulicic 0:c0ecb8bf28eb 24659 */
Marko Mikulicic 0:c0ecb8bf28eb 24660 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24661 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24662 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24663 bcode_op(bbuilder, OP_PUSH_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 24664 break;
Marko Mikulicic 0:c0ecb8bf28eb 24665 }
Marko Mikulicic 0:c0ecb8bf28eb 24666
Marko Mikulicic 0:c0ecb8bf28eb 24667 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24668 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24669 }
Marko Mikulicic 0:c0ecb8bf28eb 24670
Marko Mikulicic 0:c0ecb8bf28eb 24671 V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24672 struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 24673 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24674 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24675 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24676 enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24677
Marko Mikulicic 0:c0ecb8bf28eb 24678 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24679 case AST_ADD:
Marko Mikulicic 0:c0ecb8bf28eb 24680 case AST_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 24681 case AST_REM:
Marko Mikulicic 0:c0ecb8bf28eb 24682 case AST_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 24683 case AST_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 24684 case AST_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24685 case AST_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24686 case AST_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24687 case AST_OR:
Marko Mikulicic 0:c0ecb8bf28eb 24688 case AST_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 24689 case AST_AND:
Marko Mikulicic 0:c0ecb8bf28eb 24690 case AST_EQ_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24691 case AST_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24692 case AST_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24693 case AST_NE_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24694 case AST_LT:
Marko Mikulicic 0:c0ecb8bf28eb 24695 case AST_LE:
Marko Mikulicic 0:c0ecb8bf28eb 24696 case AST_GT:
Marko Mikulicic 0:c0ecb8bf28eb 24697 case AST_GE:
Marko Mikulicic 0:c0ecb8bf28eb 24698 case AST_INSTANCEOF:
Marko Mikulicic 0:c0ecb8bf28eb 24699 V7_TRY(compile_binary(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24700 break;
Marko Mikulicic 0:c0ecb8bf28eb 24701 case AST_LOGICAL_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 24702 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24703 bcode_op(bbuilder, OP_LOGICAL_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 24704 break;
Marko Mikulicic 0:c0ecb8bf28eb 24705 case AST_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 24706 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24707 bcode_op(bbuilder, OP_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 24708 break;
Marko Mikulicic 0:c0ecb8bf28eb 24709 case AST_POSITIVE:
Marko Mikulicic 0:c0ecb8bf28eb 24710 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24711 bcode_op(bbuilder, OP_POS);
Marko Mikulicic 0:c0ecb8bf28eb 24712 break;
Marko Mikulicic 0:c0ecb8bf28eb 24713 case AST_NEGATIVE:
Marko Mikulicic 0:c0ecb8bf28eb 24714 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24715 bcode_op(bbuilder, OP_NEG);
Marko Mikulicic 0:c0ecb8bf28eb 24716 break;
Marko Mikulicic 0:c0ecb8bf28eb 24717 case AST_IDENT:
Marko Mikulicic 0:c0ecb8bf28eb 24718 bcode_op_lit(bbuilder, OP_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 24719 string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 24720 break;
Marko Mikulicic 0:c0ecb8bf28eb 24721 case AST_MEMBER:
Marko Mikulicic 0:c0ecb8bf28eb 24722 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24723 /*
Marko Mikulicic 0:c0ecb8bf28eb 24724 * These two are handled by the "extended" version of this function,
Marko Mikulicic 0:c0ecb8bf28eb 24725 * since we may need to put `this` value on stack, for "method pattern
Marko Mikulicic 0:c0ecb8bf28eb 24726 * invocation".
Marko Mikulicic 0:c0ecb8bf28eb 24727 *
Marko Mikulicic 0:c0ecb8bf28eb 24728 * First of all, restore starting AST position, and then call extended
Marko Mikulicic 0:c0ecb8bf28eb 24729 * function.
Marko Mikulicic 0:c0ecb8bf28eb 24730 */
Marko Mikulicic 0:c0ecb8bf28eb 24731 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24732 V7_TRY(compile_expr_ext(bbuilder, a, ppos, 0 /*not for call*/));
Marko Mikulicic 0:c0ecb8bf28eb 24733 break;
Marko Mikulicic 0:c0ecb8bf28eb 24734 case AST_IN:
Marko Mikulicic 0:c0ecb8bf28eb 24735 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24736 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24737 bcode_op(bbuilder, OP_IN);
Marko Mikulicic 0:c0ecb8bf28eb 24738 break;
Marko Mikulicic 0:c0ecb8bf28eb 24739 case AST_TYPEOF: {
Marko Mikulicic 0:c0ecb8bf28eb 24740 ast_off_t lookahead = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 24741 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24742 if (tag == AST_IDENT) {
Marko Mikulicic 0:c0ecb8bf28eb 24743 *ppos = lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 24744 bcode_op_lit(bbuilder, OP_SAFE_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 24745 string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 24746 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24747 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24748 }
Marko Mikulicic 0:c0ecb8bf28eb 24749 bcode_op(bbuilder, OP_TYPEOF);
Marko Mikulicic 0:c0ecb8bf28eb 24750 break;
Marko Mikulicic 0:c0ecb8bf28eb 24751 }
Marko Mikulicic 0:c0ecb8bf28eb 24752 case AST_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24753 case AST_PREINC:
Marko Mikulicic 0:c0ecb8bf28eb 24754 case AST_PREDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24755 case AST_POSTINC:
Marko Mikulicic 0:c0ecb8bf28eb 24756 case AST_POSTDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24757 case AST_REM_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24758 case AST_MUL_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24759 case AST_DIV_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24760 case AST_XOR_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24761 case AST_PLUS_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24762 case AST_MINUS_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24763 case AST_OR_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24764 case AST_AND_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24765 case AST_LSHIFT_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24766 case AST_RSHIFT_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24767 case AST_URSHIFT_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24768 V7_TRY(compile_assign(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24769 break;
Marko Mikulicic 0:c0ecb8bf28eb 24770 case AST_COND: {
Marko Mikulicic 0:c0ecb8bf28eb 24771 /*
Marko Mikulicic 0:c0ecb8bf28eb 24772 * A ? B : C
Marko Mikulicic 0:c0ecb8bf28eb 24773 *
Marko Mikulicic 0:c0ecb8bf28eb 24774 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24775 *
Marko Mikulicic 0:c0ecb8bf28eb 24776 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24777 * JMP_FALSE false
Marko Mikulicic 0:c0ecb8bf28eb 24778 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24779 * JMP end
Marko Mikulicic 0:c0ecb8bf28eb 24780 * false:
Marko Mikulicic 0:c0ecb8bf28eb 24781 * <C>
Marko Mikulicic 0:c0ecb8bf28eb 24782 * end:
Marko Mikulicic 0:c0ecb8bf28eb 24783 *
Marko Mikulicic 0:c0ecb8bf28eb 24784 */
Marko Mikulicic 0:c0ecb8bf28eb 24785 bcode_off_t false_label, end_label;
Marko Mikulicic 0:c0ecb8bf28eb 24786 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24787 false_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 24788 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24789 end_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 24790 bcode_patch_target(bbuilder, false_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 24791 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24792 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 24793 break;
Marko Mikulicic 0:c0ecb8bf28eb 24794 }
Marko Mikulicic 0:c0ecb8bf28eb 24795 case AST_LOGICAL_OR:
Marko Mikulicic 0:c0ecb8bf28eb 24796 case AST_LOGICAL_AND: {
Marko Mikulicic 0:c0ecb8bf28eb 24797 /*
Marko Mikulicic 0:c0ecb8bf28eb 24798 * A && B
Marko Mikulicic 0:c0ecb8bf28eb 24799 *
Marko Mikulicic 0:c0ecb8bf28eb 24800 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24801 *
Marko Mikulicic 0:c0ecb8bf28eb 24802 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24803 * JMP_FALSE end
Marko Mikulicic 0:c0ecb8bf28eb 24804 * POP
Marko Mikulicic 0:c0ecb8bf28eb 24805 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24806 * end:
Marko Mikulicic 0:c0ecb8bf28eb 24807 *
Marko Mikulicic 0:c0ecb8bf28eb 24808 */
Marko Mikulicic 0:c0ecb8bf28eb 24809 bcode_off_t end_label;
Marko Mikulicic 0:c0ecb8bf28eb 24810 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24811 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24812 end_label = bcode_op_target(
Marko Mikulicic 0:c0ecb8bf28eb 24813 bbuilder, tag == AST_LOGICAL_AND ? OP_JMP_FALSE : OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 24814 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24815 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24816 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 24817 break;
Marko Mikulicic 0:c0ecb8bf28eb 24818 }
Marko Mikulicic 0:c0ecb8bf28eb 24819 /*
Marko Mikulicic 0:c0ecb8bf28eb 24820 * A, B, C
Marko Mikulicic 0:c0ecb8bf28eb 24821 *
Marko Mikulicic 0:c0ecb8bf28eb 24822 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24823 *
Marko Mikulicic 0:c0ecb8bf28eb 24824 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24825 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 24826 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24827 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 24828 * <C>
Marko Mikulicic 0:c0ecb8bf28eb 24829 */
Marko Mikulicic 0:c0ecb8bf28eb 24830 case AST_SEQ: {
Marko Mikulicic 0:c0ecb8bf28eb 24831 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24832 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 24833 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24834 if (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 24835 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24836 }
Marko Mikulicic 0:c0ecb8bf28eb 24837 }
Marko Mikulicic 0:c0ecb8bf28eb 24838 break;
Marko Mikulicic 0:c0ecb8bf28eb 24839 }
Marko Mikulicic 0:c0ecb8bf28eb 24840 case AST_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 24841 case AST_NEW: {
Marko Mikulicic 0:c0ecb8bf28eb 24842 /*
Marko Mikulicic 0:c0ecb8bf28eb 24843 * f()
Marko Mikulicic 0:c0ecb8bf28eb 24844 *
Marko Mikulicic 0:c0ecb8bf28eb 24845 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24846 *
Marko Mikulicic 0:c0ecb8bf28eb 24847 * PUSH_UNDEFINED (value for `this`)
Marko Mikulicic 0:c0ecb8bf28eb 24848 * GET_VAR "f"
Marko Mikulicic 0:c0ecb8bf28eb 24849 * CHECK_CALL
Marko Mikulicic 0:c0ecb8bf28eb 24850 * CALL 0 args
Marko Mikulicic 0:c0ecb8bf28eb 24851 *
Marko Mikulicic 0:c0ecb8bf28eb 24852 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 24853 *
Marko Mikulicic 0:c0ecb8bf28eb 24854 * f(a, b)
Marko Mikulicic 0:c0ecb8bf28eb 24855 *
Marko Mikulicic 0:c0ecb8bf28eb 24856 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24857 *
Marko Mikulicic 0:c0ecb8bf28eb 24858 * PUSH_UNDEFINED (value for `this`)
Marko Mikulicic 0:c0ecb8bf28eb 24859 * GET_VAR "f"
Marko Mikulicic 0:c0ecb8bf28eb 24860 * CHECK_CALL
Marko Mikulicic 0:c0ecb8bf28eb 24861 * GET_VAR "a"
Marko Mikulicic 0:c0ecb8bf28eb 24862 * GET_VAR "b"
Marko Mikulicic 0:c0ecb8bf28eb 24863 * CALL 2 args
Marko Mikulicic 0:c0ecb8bf28eb 24864 *
Marko Mikulicic 0:c0ecb8bf28eb 24865 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 24866 *
Marko Mikulicic 0:c0ecb8bf28eb 24867 * o.f(a, b)
Marko Mikulicic 0:c0ecb8bf28eb 24868 *
Marko Mikulicic 0:c0ecb8bf28eb 24869 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24870 *
Marko Mikulicic 0:c0ecb8bf28eb 24871 * GET_VAR "o" (so that `this` will be an `o`)
Marko Mikulicic 0:c0ecb8bf28eb 24872 * DUP (we'll also need `o` for GET below, so, duplicate it)
Marko Mikulicic 0:c0ecb8bf28eb 24873 * PUSH_LIT "f"
Marko Mikulicic 0:c0ecb8bf28eb 24874 * GET (get property "f" of the object "o")
Marko Mikulicic 0:c0ecb8bf28eb 24875 * CHECK_CALL
Marko Mikulicic 0:c0ecb8bf28eb 24876 * GET_VAR "a"
Marko Mikulicic 0:c0ecb8bf28eb 24877 * GET_VAR "b"
Marko Mikulicic 0:c0ecb8bf28eb 24878 * CALL 2 args
Marko Mikulicic 0:c0ecb8bf28eb 24879 *
Marko Mikulicic 0:c0ecb8bf28eb 24880 */
Marko Mikulicic 0:c0ecb8bf28eb 24881 int args;
Marko Mikulicic 0:c0ecb8bf28eb 24882 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24883
Marko Mikulicic 0:c0ecb8bf28eb 24884 V7_TRY(compile_expr_ext(bbuilder, a, ppos, 1 /*for call*/));
Marko Mikulicic 0:c0ecb8bf28eb 24885 bcode_op(bbuilder, OP_CHECK_CALL);
Marko Mikulicic 0:c0ecb8bf28eb 24886 for (args = 0; *ppos < end; args++) {
Marko Mikulicic 0:c0ecb8bf28eb 24887 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24888 }
Marko Mikulicic 0:c0ecb8bf28eb 24889 bcode_op(bbuilder, (tag == AST_CALL ? OP_CALL : OP_NEW));
Marko Mikulicic 0:c0ecb8bf28eb 24890 if (args > 0x7f) {
Marko Mikulicic 0:c0ecb8bf28eb 24891 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "too many arguments");
Marko Mikulicic 0:c0ecb8bf28eb 24892 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24893 }
Marko Mikulicic 0:c0ecb8bf28eb 24894 bcode_op(bbuilder, (uint8_t) args);
Marko Mikulicic 0:c0ecb8bf28eb 24895 break;
Marko Mikulicic 0:c0ecb8bf28eb 24896 }
Marko Mikulicic 0:c0ecb8bf28eb 24897 case AST_DELETE: {
Marko Mikulicic 0:c0ecb8bf28eb 24898 V7_TRY(compile_delete(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24899 break;
Marko Mikulicic 0:c0ecb8bf28eb 24900 }
Marko Mikulicic 0:c0ecb8bf28eb 24901 case AST_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 24902 /*
Marko Mikulicic 0:c0ecb8bf28eb 24903 * {a:<B>, ...}
Marko Mikulicic 0:c0ecb8bf28eb 24904 *
Marko Mikulicic 0:c0ecb8bf28eb 24905 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24906 *
Marko Mikulicic 0:c0ecb8bf28eb 24907 * CREATE_OBJ
Marko Mikulicic 0:c0ecb8bf28eb 24908 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 24909 * PUSH_LIT "a"
Marko Mikulicic 0:c0ecb8bf28eb 24910 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24911 * SET
Marko Mikulicic 0:c0ecb8bf28eb 24912 * POP
Marko Mikulicic 0:c0ecb8bf28eb 24913 * ...
Marko Mikulicic 0:c0ecb8bf28eb 24914 */
Marko Mikulicic 0:c0ecb8bf28eb 24915
Marko Mikulicic 0:c0ecb8bf28eb 24916 /*
Marko Mikulicic 0:c0ecb8bf28eb 24917 * Literal indices of property names of current object literal.
Marko Mikulicic 0:c0ecb8bf28eb 24918 * Needed for strict mode: we need to keep track of the added
Marko Mikulicic 0:c0ecb8bf28eb 24919 * properties, since duplicates are not allowed
Marko Mikulicic 0:c0ecb8bf28eb 24920 */
Marko Mikulicic 0:c0ecb8bf28eb 24921 struct mbuf cur_literals;
Marko Mikulicic 0:c0ecb8bf28eb 24922 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 24923 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24924 mbuf_init(&cur_literals, 0);
Marko Mikulicic 0:c0ecb8bf28eb 24925
Marko Mikulicic 0:c0ecb8bf28eb 24926 bcode_op(bbuilder, OP_CREATE_OBJ);
Marko Mikulicic 0:c0ecb8bf28eb 24927 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 24928 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24929 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24930 case AST_PROP:
Marko Mikulicic 0:c0ecb8bf28eb 24931 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24932 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24933
Marko Mikulicic 0:c0ecb8bf28eb 24934 /* disabled because we broke get_lit */
Marko Mikulicic 0:c0ecb8bf28eb 24935 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 24936 if (bbuilder->bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 24937 /*
Marko Mikulicic 0:c0ecb8bf28eb 24938 * In strict mode, check for duplicate property names in
Marko Mikulicic 0:c0ecb8bf28eb 24939 * object literals
Marko Mikulicic 0:c0ecb8bf28eb 24940 */
Marko Mikulicic 0:c0ecb8bf28eb 24941 char *plit;
Marko Mikulicic 0:c0ecb8bf28eb 24942 for (plit = (char *) cur_literals.buf;
Marko Mikulicic 0:c0ecb8bf28eb 24943 (char *) plit < cur_literals.buf + cur_literals.len;
Marko Mikulicic 0:c0ecb8bf28eb 24944 plit++) {
Marko Mikulicic 0:c0ecb8bf28eb 24945 const char *str1, *str2;
Marko Mikulicic 0:c0ecb8bf28eb 24946 size_t size1, size2;
Marko Mikulicic 0:c0ecb8bf28eb 24947 v7_val_t val1, val2;
Marko Mikulicic 0:c0ecb8bf28eb 24948
Marko Mikulicic 0:c0ecb8bf28eb 24949 val1 = bcode_get_lit(bbuilder->bcode, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24950 str1 = v7_get_string(bbuilder->v7, &val1, &size1);
Marko Mikulicic 0:c0ecb8bf28eb 24951
Marko Mikulicic 0:c0ecb8bf28eb 24952 val2 = bcode_get_lit(bbuilder->bcode, *plit);
Marko Mikulicic 0:c0ecb8bf28eb 24953 str2 = v7_get_string(bbuilder->v7, &val2, &size2);
Marko Mikulicic 0:c0ecb8bf28eb 24954
Marko Mikulicic 0:c0ecb8bf28eb 24955 if (size1 == size2 && memcmp(str1, str2, size1) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 24956 /* found already existing property of the same name */
Marko Mikulicic 0:c0ecb8bf28eb 24957 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 24958 "duplicate data property in object literal "
Marko Mikulicic 0:c0ecb8bf28eb 24959 "is not allowed in strict mode");
Marko Mikulicic 0:c0ecb8bf28eb 24960 V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean);
Marko Mikulicic 0:c0ecb8bf28eb 24961 }
Marko Mikulicic 0:c0ecb8bf28eb 24962 }
Marko Mikulicic 0:c0ecb8bf28eb 24963 mbuf_append(&cur_literals, &lit, sizeof(lit));
Marko Mikulicic 0:c0ecb8bf28eb 24964 }
Marko Mikulicic 0:c0ecb8bf28eb 24965 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24966 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24967 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24968 bcode_op(bbuilder, OP_SET);
Marko Mikulicic 0:c0ecb8bf28eb 24969 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24970 break;
Marko Mikulicic 0:c0ecb8bf28eb 24971 default:
Marko Mikulicic 0:c0ecb8bf28eb 24972 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
Marko Mikulicic 0:c0ecb8bf28eb 24973 V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean);
Marko Mikulicic 0:c0ecb8bf28eb 24974 }
Marko Mikulicic 0:c0ecb8bf28eb 24975 }
Marko Mikulicic 0:c0ecb8bf28eb 24976
Marko Mikulicic 0:c0ecb8bf28eb 24977 ast_object_clean:
Marko Mikulicic 0:c0ecb8bf28eb 24978 mbuf_free(&cur_literals);
Marko Mikulicic 0:c0ecb8bf28eb 24979 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 24980 V7_THROW(rcode);
Marko Mikulicic 0:c0ecb8bf28eb 24981 }
Marko Mikulicic 0:c0ecb8bf28eb 24982 break;
Marko Mikulicic 0:c0ecb8bf28eb 24983 }
Marko Mikulicic 0:c0ecb8bf28eb 24984 case AST_ARRAY: {
Marko Mikulicic 0:c0ecb8bf28eb 24985 /*
Marko Mikulicic 0:c0ecb8bf28eb 24986 * [<A>,,<B>,...]
Marko Mikulicic 0:c0ecb8bf28eb 24987 *
Marko Mikulicic 0:c0ecb8bf28eb 24988 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24989 *
Marko Mikulicic 0:c0ecb8bf28eb 24990 * CREATE_ARR
Marko Mikulicic 0:c0ecb8bf28eb 24991 * PUSH_ZERO
Marko Mikulicic 0:c0ecb8bf28eb 24992 *
Marko Mikulicic 0:c0ecb8bf28eb 24993 * 2DUP
Marko Mikulicic 0:c0ecb8bf28eb 24994 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24995 * SET
Marko Mikulicic 0:c0ecb8bf28eb 24996 * POP
Marko Mikulicic 0:c0ecb8bf28eb 24997 * PUSH_ONE
Marko Mikulicic 0:c0ecb8bf28eb 24998 * ADD
Marko Mikulicic 0:c0ecb8bf28eb 24999 *
Marko Mikulicic 0:c0ecb8bf28eb 25000 * PUSH_ONE
Marko Mikulicic 0:c0ecb8bf28eb 25001 * ADD
Marko Mikulicic 0:c0ecb8bf28eb 25002 *
Marko Mikulicic 0:c0ecb8bf28eb 25003 * 2DUP
Marko Mikulicic 0:c0ecb8bf28eb 25004 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25005 * ...
Marko Mikulicic 0:c0ecb8bf28eb 25006 * POP // tmp index
Marko Mikulicic 0:c0ecb8bf28eb 25007 *
Marko Mikulicic 0:c0ecb8bf28eb 25008 * TODO(mkm): optimize this out. we can have more compact array push
Marko Mikulicic 0:c0ecb8bf28eb 25009 * that uses a special marker value for missing array elements
Marko Mikulicic 0:c0ecb8bf28eb 25010 * (which are not the same as undefined btw)
Marko Mikulicic 0:c0ecb8bf28eb 25011 */
Marko Mikulicic 0:c0ecb8bf28eb 25012 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25013 bcode_op(bbuilder, OP_CREATE_ARR);
Marko Mikulicic 0:c0ecb8bf28eb 25014 bcode_op(bbuilder, OP_PUSH_ZERO);
Marko Mikulicic 0:c0ecb8bf28eb 25015 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25016 ast_off_t lookahead = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25017 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25018 if (tag != AST_NOP) {
Marko Mikulicic 0:c0ecb8bf28eb 25019 bcode_op(bbuilder, OP_2DUP);
Marko Mikulicic 0:c0ecb8bf28eb 25020 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25021 bcode_op(bbuilder, OP_SET);
Marko Mikulicic 0:c0ecb8bf28eb 25022 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25023 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25024 *ppos = lookahead; /* skip nop */
Marko Mikulicic 0:c0ecb8bf28eb 25025 }
Marko Mikulicic 0:c0ecb8bf28eb 25026 bcode_op(bbuilder, OP_PUSH_ONE);
Marko Mikulicic 0:c0ecb8bf28eb 25027 bcode_op(bbuilder, OP_ADD);
Marko Mikulicic 0:c0ecb8bf28eb 25028 }
Marko Mikulicic 0:c0ecb8bf28eb 25029 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25030 break;
Marko Mikulicic 0:c0ecb8bf28eb 25031 }
Marko Mikulicic 0:c0ecb8bf28eb 25032 case AST_FUNC: {
Marko Mikulicic 0:c0ecb8bf28eb 25033 lit_t flit;
Marko Mikulicic 0:c0ecb8bf28eb 25034
Marko Mikulicic 0:c0ecb8bf28eb 25035 /*
Marko Mikulicic 0:c0ecb8bf28eb 25036 * Create half-done function: without scope and prototype. The real
Marko Mikulicic 0:c0ecb8bf28eb 25037 * function will be created from this one during bcode evaluation: see
Marko Mikulicic 0:c0ecb8bf28eb 25038 * `bcode_instantiate_function()`.
Marko Mikulicic 0:c0ecb8bf28eb 25039 */
Marko Mikulicic 0:c0ecb8bf28eb 25040 val_t funv = mk_js_function(bbuilder->v7, NULL, V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25041
Marko Mikulicic 0:c0ecb8bf28eb 25042 /* Create bcode in this half-done function */
Marko Mikulicic 0:c0ecb8bf28eb 25043 struct v7_js_function *func = get_js_function_struct(funv);
Marko Mikulicic 0:c0ecb8bf28eb 25044 func->bcode = (struct bcode *) calloc(1, sizeof(*bbuilder->bcode));
Marko Mikulicic 0:c0ecb8bf28eb 25045 bcode_init(func->bcode, bbuilder->bcode->strict_mode,
Marko Mikulicic 0:c0ecb8bf28eb 25046 NULL /* will be set below */, 0);
Marko Mikulicic 0:c0ecb8bf28eb 25047 bcode_copy_filename_from(func->bcode, bbuilder->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25048 retain_bcode(bbuilder->v7, func->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25049 flit = bcode_add_lit(bbuilder, funv);
Marko Mikulicic 0:c0ecb8bf28eb 25050
Marko Mikulicic 0:c0ecb8bf28eb 25051 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25052 V7_TRY(compile_function(v7, a, ppos, func->bcode));
Marko Mikulicic 0:c0ecb8bf28eb 25053 bcode_push_lit(bbuilder, flit);
Marko Mikulicic 0:c0ecb8bf28eb 25054 bcode_op(bbuilder, OP_FUNC_LIT);
Marko Mikulicic 0:c0ecb8bf28eb 25055 break;
Marko Mikulicic 0:c0ecb8bf28eb 25056 }
Marko Mikulicic 0:c0ecb8bf28eb 25057 case AST_THIS:
Marko Mikulicic 0:c0ecb8bf28eb 25058 bcode_op(bbuilder, OP_PUSH_THIS);
Marko Mikulicic 0:c0ecb8bf28eb 25059 break;
Marko Mikulicic 0:c0ecb8bf28eb 25060 case AST_VOID:
Marko Mikulicic 0:c0ecb8bf28eb 25061 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25062 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25063 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25064 break;
Marko Mikulicic 0:c0ecb8bf28eb 25065 case AST_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 25066 bcode_op(bbuilder, OP_PUSH_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 25067 break;
Marko Mikulicic 0:c0ecb8bf28eb 25068 case AST_NOP:
Marko Mikulicic 0:c0ecb8bf28eb 25069 case AST_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 25070 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25071 break;
Marko Mikulicic 0:c0ecb8bf28eb 25072 case AST_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 25073 bcode_op(bbuilder, OP_PUSH_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25074 break;
Marko Mikulicic 0:c0ecb8bf28eb 25075 case AST_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 25076 bcode_op(bbuilder, OP_PUSH_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 25077 break;
Marko Mikulicic 0:c0ecb8bf28eb 25078 case AST_NUM: {
Marko Mikulicic 0:c0ecb8bf28eb 25079 double dv = ast_get_num(a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25080 if (dv == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 25081 bcode_op(bbuilder, OP_PUSH_ZERO);
Marko Mikulicic 0:c0ecb8bf28eb 25082 } else if (dv == 1) {
Marko Mikulicic 0:c0ecb8bf28eb 25083 bcode_op(bbuilder, OP_PUSH_ONE);
Marko Mikulicic 0:c0ecb8bf28eb 25084 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25085 bcode_push_lit(bbuilder, bcode_add_lit(bbuilder, v7_mk_number(v7, dv)));
Marko Mikulicic 0:c0ecb8bf28eb 25086 }
Marko Mikulicic 0:c0ecb8bf28eb 25087 break;
Marko Mikulicic 0:c0ecb8bf28eb 25088 }
Marko Mikulicic 0:c0ecb8bf28eb 25089 case AST_STRING:
Marko Mikulicic 0:c0ecb8bf28eb 25090 bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 25091 break;
Marko Mikulicic 0:c0ecb8bf28eb 25092 case AST_REGEX:
Marko Mikulicic 0:c0ecb8bf28eb 25093 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 25094 {
Marko Mikulicic 0:c0ecb8bf28eb 25095 lit_t tmp;
Marko Mikulicic 0:c0ecb8bf28eb 25096 rcode = regexp_lit(bbuilder, a, pos_after_tag, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 25097 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 25098 rcode = V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 25099 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 25100 }
Marko Mikulicic 0:c0ecb8bf28eb 25101
Marko Mikulicic 0:c0ecb8bf28eb 25102 bcode_push_lit(bbuilder, tmp);
Marko Mikulicic 0:c0ecb8bf28eb 25103 break;
Marko Mikulicic 0:c0ecb8bf28eb 25104 }
Marko Mikulicic 0:c0ecb8bf28eb 25105 #else
Marko Mikulicic 0:c0ecb8bf28eb 25106 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 25107 v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Regexp support is disabled");
Marko Mikulicic 0:c0ecb8bf28eb 25108 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25109 #endif
Marko Mikulicic 0:c0ecb8bf28eb 25110 case AST_LABEL:
Marko Mikulicic 0:c0ecb8bf28eb 25111 case AST_LABELED_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 25112 case AST_LABELED_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 25113 /* TODO(dfrank): implement */
Marko Mikulicic 0:c0ecb8bf28eb 25114 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
Marko Mikulicic 0:c0ecb8bf28eb 25115 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25116 case AST_WITH:
Marko Mikulicic 0:c0ecb8bf28eb 25117 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
Marko Mikulicic 0:c0ecb8bf28eb 25118 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25119 default:
Marko Mikulicic 0:c0ecb8bf28eb 25120 /*
Marko Mikulicic 0:c0ecb8bf28eb 25121 * We end up here if the AST is broken.
Marko Mikulicic 0:c0ecb8bf28eb 25122 *
Marko Mikulicic 0:c0ecb8bf28eb 25123 * It might be appropriate to return `V7_INTERNAL_ERROR` here, but since
Marko Mikulicic 0:c0ecb8bf28eb 25124 * we might receive AST from network or something, we just interpret
Marko Mikulicic 0:c0ecb8bf28eb 25125 * it as SyntaxError.
Marko Mikulicic 0:c0ecb8bf28eb 25126 */
Marko Mikulicic 0:c0ecb8bf28eb 25127 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown ast node %d",
Marko Mikulicic 0:c0ecb8bf28eb 25128 (int) tag);
Marko Mikulicic 0:c0ecb8bf28eb 25129 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25130 }
Marko Mikulicic 0:c0ecb8bf28eb 25131 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25132 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25133 }
Marko Mikulicic 0:c0ecb8bf28eb 25134
Marko Mikulicic 0:c0ecb8bf28eb 25135 V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 25136 struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25137
Marko Mikulicic 0:c0ecb8bf28eb 25138 V7_PRIVATE enum v7_err compile_stmts(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 25139 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 25140 ast_off_t end) {
Marko Mikulicic 0:c0ecb8bf28eb 25141 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25142 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 25143
Marko Mikulicic 0:c0ecb8bf28eb 25144 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25145 V7_TRY(compile_stmt(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25146 if (!bbuilder->v7->is_stack_neutral) {
Marko Mikulicic 0:c0ecb8bf28eb 25147 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25148 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25149 bbuilder->v7->is_stack_neutral = 0;
Marko Mikulicic 0:c0ecb8bf28eb 25150 }
Marko Mikulicic 0:c0ecb8bf28eb 25151 }
Marko Mikulicic 0:c0ecb8bf28eb 25152 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25153 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25154 }
Marko Mikulicic 0:c0ecb8bf28eb 25155
Marko Mikulicic 0:c0ecb8bf28eb 25156 V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 25157 struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 25158 ast_off_t end;
Marko Mikulicic 0:c0ecb8bf28eb 25159 enum ast_tag tag;
Marko Mikulicic 0:c0ecb8bf28eb 25160 ast_off_t cond, pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 25161 bcode_off_t body_target, body_label, cond_label;
Marko Mikulicic 0:c0ecb8bf28eb 25162 struct mbuf case_labels;
Marko Mikulicic 0:c0ecb8bf28eb 25163 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25164 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 25165
Marko Mikulicic 0:c0ecb8bf28eb 25166 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25167
Marko Mikulicic 0:c0ecb8bf28eb 25168 mbuf_init(&case_labels, 0);
Marko Mikulicic 0:c0ecb8bf28eb 25169
Marko Mikulicic 0:c0ecb8bf28eb 25170 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 25171 /*
Marko Mikulicic 0:c0ecb8bf28eb 25172 * if(E) {
Marko Mikulicic 0:c0ecb8bf28eb 25173 * BT...
Marko Mikulicic 0:c0ecb8bf28eb 25174 * } else {
Marko Mikulicic 0:c0ecb8bf28eb 25175 * BF...
Marko Mikulicic 0:c0ecb8bf28eb 25176 * }
Marko Mikulicic 0:c0ecb8bf28eb 25177 *
Marko Mikulicic 0:c0ecb8bf28eb 25178 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25179 *
Marko Mikulicic 0:c0ecb8bf28eb 25180 * <E>
Marko Mikulicic 0:c0ecb8bf28eb 25181 * JMP_FALSE body
Marko Mikulicic 0:c0ecb8bf28eb 25182 * <BT>
Marko Mikulicic 0:c0ecb8bf28eb 25183 * JMP end
Marko Mikulicic 0:c0ecb8bf28eb 25184 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25185 * <BF>
Marko Mikulicic 0:c0ecb8bf28eb 25186 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25187 *
Marko Mikulicic 0:c0ecb8bf28eb 25188 * If else clause is omitted, it will emit output equivalent to:
Marko Mikulicic 0:c0ecb8bf28eb 25189 *
Marko Mikulicic 0:c0ecb8bf28eb 25190 * if(E) {BT} else undefined;
Marko Mikulicic 0:c0ecb8bf28eb 25191 */
Marko Mikulicic 0:c0ecb8bf28eb 25192 case AST_IF: {
Marko Mikulicic 0:c0ecb8bf28eb 25193 ast_off_t if_false;
Marko Mikulicic 0:c0ecb8bf28eb 25194 bcode_off_t end_label, if_false_label;
Marko Mikulicic 0:c0ecb8bf28eb 25195 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25196 if_false = ast_get_skip(a, pos_after_tag, AST_END_IF_TRUE_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25197
Marko Mikulicic 0:c0ecb8bf28eb 25198 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25199 if_false_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 25200
Marko Mikulicic 0:c0ecb8bf28eb 25201 /* body if true */
Marko Mikulicic 0:c0ecb8bf28eb 25202 V7_TRY(compile_stmts(bbuilder, a, ppos, if_false));
Marko Mikulicic 0:c0ecb8bf28eb 25203
Marko Mikulicic 0:c0ecb8bf28eb 25204 if (if_false != end) {
Marko Mikulicic 0:c0ecb8bf28eb 25205 /* `else` branch is present */
Marko Mikulicic 0:c0ecb8bf28eb 25206 end_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25207
Marko Mikulicic 0:c0ecb8bf28eb 25208 /* will jump here if `false` */
Marko Mikulicic 0:c0ecb8bf28eb 25209 bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25210
Marko Mikulicic 0:c0ecb8bf28eb 25211 /* body if false */
Marko Mikulicic 0:c0ecb8bf28eb 25212 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25213
Marko Mikulicic 0:c0ecb8bf28eb 25214 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25215 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25216 /*
Marko Mikulicic 0:c0ecb8bf28eb 25217 * `else` branch is not present: just remember where we should
Marko Mikulicic 0:c0ecb8bf28eb 25218 * jump in case of `false`
Marko Mikulicic 0:c0ecb8bf28eb 25219 */
Marko Mikulicic 0:c0ecb8bf28eb 25220 bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25221 }
Marko Mikulicic 0:c0ecb8bf28eb 25222
Marko Mikulicic 0:c0ecb8bf28eb 25223 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25224 break;
Marko Mikulicic 0:c0ecb8bf28eb 25225 }
Marko Mikulicic 0:c0ecb8bf28eb 25226 /*
Marko Mikulicic 0:c0ecb8bf28eb 25227 * while(C) {
Marko Mikulicic 0:c0ecb8bf28eb 25228 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25229 * }
Marko Mikulicic 0:c0ecb8bf28eb 25230 *
Marko Mikulicic 0:c0ecb8bf28eb 25231 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25232 *
Marko Mikulicic 0:c0ecb8bf28eb 25233 * TRY_PUSH_LOOP end
Marko Mikulicic 0:c0ecb8bf28eb 25234 * JMP cond
Marko Mikulicic 0:c0ecb8bf28eb 25235 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25236 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25237 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 25238 * <C>
Marko Mikulicic 0:c0ecb8bf28eb 25239 * JMP_TRUE body
Marko Mikulicic 0:c0ecb8bf28eb 25240 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25241 * JMP_IF_CONTINUE cond
Marko Mikulicic 0:c0ecb8bf28eb 25242 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25243 *
Marko Mikulicic 0:c0ecb8bf28eb 25244 */
Marko Mikulicic 0:c0ecb8bf28eb 25245 case AST_WHILE: {
Marko Mikulicic 0:c0ecb8bf28eb 25246 bcode_off_t end_label, continue_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25247
Marko Mikulicic 0:c0ecb8bf28eb 25248 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25249 cond = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25250 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25251
Marko Mikulicic 0:c0ecb8bf28eb 25252 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25253
Marko Mikulicic 0:c0ecb8bf28eb 25254 /*
Marko Mikulicic 0:c0ecb8bf28eb 25255 * Condition check is at the end of the loop, this layout
Marko Mikulicic 0:c0ecb8bf28eb 25256 * reduces the number of jumps in the steady state.
Marko Mikulicic 0:c0ecb8bf28eb 25257 */
Marko Mikulicic 0:c0ecb8bf28eb 25258 cond_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25259 body_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25260
Marko Mikulicic 0:c0ecb8bf28eb 25261 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25262
Marko Mikulicic 0:c0ecb8bf28eb 25263 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25264 bcode_patch_target(bbuilder, cond_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25265
Marko Mikulicic 0:c0ecb8bf28eb 25266 V7_TRY(compile_expr_builder(bbuilder, a, &cond));
Marko Mikulicic 0:c0ecb8bf28eb 25267 body_label = bcode_op_target(bbuilder, OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25268 bcode_patch_target(bbuilder, body_label, body_target);
Marko Mikulicic 0:c0ecb8bf28eb 25269
Marko Mikulicic 0:c0ecb8bf28eb 25270 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25271 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25272 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25273 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25274
Marko Mikulicic 0:c0ecb8bf28eb 25275 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25276 break;
Marko Mikulicic 0:c0ecb8bf28eb 25277 }
Marko Mikulicic 0:c0ecb8bf28eb 25278 case AST_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 25279 bcode_op(bbuilder, OP_BREAK);
Marko Mikulicic 0:c0ecb8bf28eb 25280 break;
Marko Mikulicic 0:c0ecb8bf28eb 25281 case AST_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 25282 bcode_op(bbuilder, OP_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25283 break;
Marko Mikulicic 0:c0ecb8bf28eb 25284 /*
Marko Mikulicic 0:c0ecb8bf28eb 25285 * Frame objects (`v7->vals.call_stack`) contain one more hidden property:
Marko Mikulicic 0:c0ecb8bf28eb 25286 * `____t`, which is an array of offsets in bcode. Each element of the array
Marko Mikulicic 0:c0ecb8bf28eb 25287 * is an offset of either `catch` or `finally` block (distinguished by the
Marko Mikulicic 0:c0ecb8bf28eb 25288 * tag: `OFFSET_TAG_CATCH` or `OFFSET_TAG_FINALLY`). Let's call this array
Marko Mikulicic 0:c0ecb8bf28eb 25289 * as a "try stack". When evaluator enters new `try` block, it adds
Marko Mikulicic 0:c0ecb8bf28eb 25290 * appropriate offset(s) at the top of "try stack", and when we unwind the
Marko Mikulicic 0:c0ecb8bf28eb 25291 * stack, we can "pop" offsets from "try stack" at each level.
Marko Mikulicic 0:c0ecb8bf28eb 25292 *
Marko Mikulicic 0:c0ecb8bf28eb 25293 * try {
Marko Mikulicic 0:c0ecb8bf28eb 25294 * TRY_B
Marko Mikulicic 0:c0ecb8bf28eb 25295 * } catch (e) {
Marko Mikulicic 0:c0ecb8bf28eb 25296 * CATCH_B
Marko Mikulicic 0:c0ecb8bf28eb 25297 * } finally {
Marko Mikulicic 0:c0ecb8bf28eb 25298 * FIN_B
Marko Mikulicic 0:c0ecb8bf28eb 25299 * }
Marko Mikulicic 0:c0ecb8bf28eb 25300 *
Marko Mikulicic 0:c0ecb8bf28eb 25301 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25302 * OP_TRY_PUSH_FINALLY finally
Marko Mikulicic 0:c0ecb8bf28eb 25303 * OP_TRY_PUSH_CATCH catch
Marko Mikulicic 0:c0ecb8bf28eb 25304 * <TRY_B>
Marko Mikulicic 0:c0ecb8bf28eb 25305 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25306 * JMP finally
Marko Mikulicic 0:c0ecb8bf28eb 25307 * catch:
Marko Mikulicic 0:c0ecb8bf28eb 25308 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25309 * OP_ENTER_CATCH <e>
Marko Mikulicic 0:c0ecb8bf28eb 25310 * <CATCH_B>
Marko Mikulicic 0:c0ecb8bf28eb 25311 * OP_EXIT_CATCH
Marko Mikulicic 0:c0ecb8bf28eb 25312 * finally:
Marko Mikulicic 0:c0ecb8bf28eb 25313 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25314 * <FIN_B>
Marko Mikulicic 0:c0ecb8bf28eb 25315 * OP_AFTER_FINALLY
Marko Mikulicic 0:c0ecb8bf28eb 25316 *
Marko Mikulicic 0:c0ecb8bf28eb 25317 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 25318 *
Marko Mikulicic 0:c0ecb8bf28eb 25319 * try {
Marko Mikulicic 0:c0ecb8bf28eb 25320 * TRY_B
Marko Mikulicic 0:c0ecb8bf28eb 25321 * } catch (e) {
Marko Mikulicic 0:c0ecb8bf28eb 25322 * CATCH_B
Marko Mikulicic 0:c0ecb8bf28eb 25323 * }
Marko Mikulicic 0:c0ecb8bf28eb 25324 *
Marko Mikulicic 0:c0ecb8bf28eb 25325 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25326 * OP_TRY_PUSH_CATCH catch
Marko Mikulicic 0:c0ecb8bf28eb 25327 * <TRY_B>
Marko Mikulicic 0:c0ecb8bf28eb 25328 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25329 * JMP end
Marko Mikulicic 0:c0ecb8bf28eb 25330 * catch:
Marko Mikulicic 0:c0ecb8bf28eb 25331 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25332 * OP_ENTER_CATCH <e>
Marko Mikulicic 0:c0ecb8bf28eb 25333 * <CATCH_B>
Marko Mikulicic 0:c0ecb8bf28eb 25334 * OP_EXIT_CATCH
Marko Mikulicic 0:c0ecb8bf28eb 25335 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25336 *
Marko Mikulicic 0:c0ecb8bf28eb 25337 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 25338 *
Marko Mikulicic 0:c0ecb8bf28eb 25339 * try {
Marko Mikulicic 0:c0ecb8bf28eb 25340 * TRY_B
Marko Mikulicic 0:c0ecb8bf28eb 25341 * } finally {
Marko Mikulicic 0:c0ecb8bf28eb 25342 * FIN_B
Marko Mikulicic 0:c0ecb8bf28eb 25343 * }
Marko Mikulicic 0:c0ecb8bf28eb 25344 *
Marko Mikulicic 0:c0ecb8bf28eb 25345 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25346 * OP_TRY_PUSH_FINALLY finally
Marko Mikulicic 0:c0ecb8bf28eb 25347 * <TRY_B>
Marko Mikulicic 0:c0ecb8bf28eb 25348 * finally:
Marko Mikulicic 0:c0ecb8bf28eb 25349 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25350 * <FIN_B>
Marko Mikulicic 0:c0ecb8bf28eb 25351 * OP_AFTER_FINALLY
Marko Mikulicic 0:c0ecb8bf28eb 25352 */
Marko Mikulicic 0:c0ecb8bf28eb 25353 case AST_TRY: {
Marko Mikulicic 0:c0ecb8bf28eb 25354 ast_off_t acatch, afinally;
Marko Mikulicic 0:c0ecb8bf28eb 25355 bcode_off_t finally_label, catch_label;
Marko Mikulicic 0:c0ecb8bf28eb 25356
Marko Mikulicic 0:c0ecb8bf28eb 25357 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25358 acatch = ast_get_skip(a, pos_after_tag, AST_TRY_CATCH_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25359 afinally = ast_get_skip(a, pos_after_tag, AST_TRY_FINALLY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25360
Marko Mikulicic 0:c0ecb8bf28eb 25361 if (afinally != end) {
Marko Mikulicic 0:c0ecb8bf28eb 25362 /* `finally` clause is present: push its offset */
Marko Mikulicic 0:c0ecb8bf28eb 25363 finally_label = bcode_op_target(bbuilder, OP_TRY_PUSH_FINALLY);
Marko Mikulicic 0:c0ecb8bf28eb 25364 }
Marko Mikulicic 0:c0ecb8bf28eb 25365
Marko Mikulicic 0:c0ecb8bf28eb 25366 if (acatch != afinally) {
Marko Mikulicic 0:c0ecb8bf28eb 25367 /* `catch` clause is present: push its offset */
Marko Mikulicic 0:c0ecb8bf28eb 25368 catch_label = bcode_op_target(bbuilder, OP_TRY_PUSH_CATCH);
Marko Mikulicic 0:c0ecb8bf28eb 25369 }
Marko Mikulicic 0:c0ecb8bf28eb 25370
Marko Mikulicic 0:c0ecb8bf28eb 25371 /* compile statements of `try` block */
Marko Mikulicic 0:c0ecb8bf28eb 25372 V7_TRY(compile_stmts(bbuilder, a, ppos, acatch));
Marko Mikulicic 0:c0ecb8bf28eb 25373
Marko Mikulicic 0:c0ecb8bf28eb 25374 if (acatch != afinally) {
Marko Mikulicic 0:c0ecb8bf28eb 25375 /* `catch` clause is present: compile it */
Marko Mikulicic 0:c0ecb8bf28eb 25376 bcode_off_t after_catch_label;
Marko Mikulicic 0:c0ecb8bf28eb 25377
Marko Mikulicic 0:c0ecb8bf28eb 25378 /*
Marko Mikulicic 0:c0ecb8bf28eb 25379 * pop offset pushed by OP_TRY_PUSH_CATCH, and jump over the `catch`
Marko Mikulicic 0:c0ecb8bf28eb 25380 * block
Marko Mikulicic 0:c0ecb8bf28eb 25381 */
Marko Mikulicic 0:c0ecb8bf28eb 25382 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25383 after_catch_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25384
Marko Mikulicic 0:c0ecb8bf28eb 25385 /* --- catch --- */
Marko Mikulicic 0:c0ecb8bf28eb 25386
Marko Mikulicic 0:c0ecb8bf28eb 25387 /* in case of exception in the `try` block above, we'll get here */
Marko Mikulicic 0:c0ecb8bf28eb 25388 bcode_patch_target(bbuilder, catch_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25389
Marko Mikulicic 0:c0ecb8bf28eb 25390 /* pop offset pushed by OP_TRY_PUSH_CATCH */
Marko Mikulicic 0:c0ecb8bf28eb 25391 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25392
Marko Mikulicic 0:c0ecb8bf28eb 25393 /*
Marko Mikulicic 0:c0ecb8bf28eb 25394 * retrieve identifier where to store thrown error, and make sure
Marko Mikulicic 0:c0ecb8bf28eb 25395 * it is actually an indentifier (AST_IDENT)
Marko Mikulicic 0:c0ecb8bf28eb 25396 */
Marko Mikulicic 0:c0ecb8bf28eb 25397 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25398 V7_CHECK(tag == AST_IDENT, V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25399
Marko Mikulicic 0:c0ecb8bf28eb 25400 /*
Marko Mikulicic 0:c0ecb8bf28eb 25401 * when we enter `catch` block, the TOS contains thrown value.
Marko Mikulicic 0:c0ecb8bf28eb 25402 * We should create private frame for the `catch` clause, and populate
Marko Mikulicic 0:c0ecb8bf28eb 25403 * a variable with the thrown value there.
Marko Mikulicic 0:c0ecb8bf28eb 25404 * The `OP_ENTER_CATCH` opcode does just that.
Marko Mikulicic 0:c0ecb8bf28eb 25405 */
Marko Mikulicic 0:c0ecb8bf28eb 25406 bcode_op_lit(bbuilder, OP_ENTER_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 25407 string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 25408
Marko Mikulicic 0:c0ecb8bf28eb 25409 /*
Marko Mikulicic 0:c0ecb8bf28eb 25410 * compile statements until the end of `catch` clause
Marko Mikulicic 0:c0ecb8bf28eb 25411 * (`afinally` points to the end of the `catch` clause independently
Marko Mikulicic 0:c0ecb8bf28eb 25412 * of whether the `finally` clause is present)
Marko Mikulicic 0:c0ecb8bf28eb 25413 */
Marko Mikulicic 0:c0ecb8bf28eb 25414 V7_TRY(compile_stmts(bbuilder, a, ppos, afinally));
Marko Mikulicic 0:c0ecb8bf28eb 25415
Marko Mikulicic 0:c0ecb8bf28eb 25416 /* pop private frame */
Marko Mikulicic 0:c0ecb8bf28eb 25417 bcode_op(bbuilder, OP_EXIT_CATCH);
Marko Mikulicic 0:c0ecb8bf28eb 25418
Marko Mikulicic 0:c0ecb8bf28eb 25419 bcode_patch_target(bbuilder, after_catch_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25420 }
Marko Mikulicic 0:c0ecb8bf28eb 25421
Marko Mikulicic 0:c0ecb8bf28eb 25422 if (afinally != end) {
Marko Mikulicic 0:c0ecb8bf28eb 25423 /* `finally` clause is present: compile it */
Marko Mikulicic 0:c0ecb8bf28eb 25424
Marko Mikulicic 0:c0ecb8bf28eb 25425 /* --- finally --- */
Marko Mikulicic 0:c0ecb8bf28eb 25426
Marko Mikulicic 0:c0ecb8bf28eb 25427 /* after the `try` block above executes, we'll get here */
Marko Mikulicic 0:c0ecb8bf28eb 25428 bcode_patch_target(bbuilder, finally_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25429
Marko Mikulicic 0:c0ecb8bf28eb 25430 /* pop offset pushed by OP_TRY_PUSH_FINALLY */
Marko Mikulicic 0:c0ecb8bf28eb 25431 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25432
Marko Mikulicic 0:c0ecb8bf28eb 25433 /* compile statements until the end of `finally` clause */
Marko Mikulicic 0:c0ecb8bf28eb 25434 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25435
Marko Mikulicic 0:c0ecb8bf28eb 25436 bcode_op(bbuilder, OP_AFTER_FINALLY);
Marko Mikulicic 0:c0ecb8bf28eb 25437 }
Marko Mikulicic 0:c0ecb8bf28eb 25438
Marko Mikulicic 0:c0ecb8bf28eb 25439 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25440 break;
Marko Mikulicic 0:c0ecb8bf28eb 25441 }
Marko Mikulicic 0:c0ecb8bf28eb 25442
Marko Mikulicic 0:c0ecb8bf28eb 25443 case AST_THROW: {
Marko Mikulicic 0:c0ecb8bf28eb 25444 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25445 bcode_op(bbuilder, OP_THROW);
Marko Mikulicic 0:c0ecb8bf28eb 25446 break;
Marko Mikulicic 0:c0ecb8bf28eb 25447 }
Marko Mikulicic 0:c0ecb8bf28eb 25448
Marko Mikulicic 0:c0ecb8bf28eb 25449 /*
Marko Mikulicic 0:c0ecb8bf28eb 25450 * switch(E) {
Marko Mikulicic 0:c0ecb8bf28eb 25451 * default:
Marko Mikulicic 0:c0ecb8bf28eb 25452 * D...
Marko Mikulicic 0:c0ecb8bf28eb 25453 * case C1:
Marko Mikulicic 0:c0ecb8bf28eb 25454 * B1...
Marko Mikulicic 0:c0ecb8bf28eb 25455 * case C2:
Marko Mikulicic 0:c0ecb8bf28eb 25456 * B2...
Marko Mikulicic 0:c0ecb8bf28eb 25457 * }
Marko Mikulicic 0:c0ecb8bf28eb 25458 *
Marko Mikulicic 0:c0ecb8bf28eb 25459 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25460 *
Marko Mikulicic 0:c0ecb8bf28eb 25461 * TRY_PUSH_SWITCH end
Marko Mikulicic 0:c0ecb8bf28eb 25462 * <E>
Marko Mikulicic 0:c0ecb8bf28eb 25463 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 25464 * <C1>
Marko Mikulicic 0:c0ecb8bf28eb 25465 * EQ
Marko Mikulicic 0:c0ecb8bf28eb 25466 * JMP_TRUE_DROP l1
Marko Mikulicic 0:c0ecb8bf28eb 25467 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 25468 * <C2>
Marko Mikulicic 0:c0ecb8bf28eb 25469 * EQ
Marko Mikulicic 0:c0ecb8bf28eb 25470 * JMP_TRUE_DROP l2
Marko Mikulicic 0:c0ecb8bf28eb 25471 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25472 * JMP dfl
Marko Mikulicic 0:c0ecb8bf28eb 25473 *
Marko Mikulicic 0:c0ecb8bf28eb 25474 * dfl:
Marko Mikulicic 0:c0ecb8bf28eb 25475 * <D>
Marko Mikulicic 0:c0ecb8bf28eb 25476 *
Marko Mikulicic 0:c0ecb8bf28eb 25477 * l1:
Marko Mikulicic 0:c0ecb8bf28eb 25478 * <B1>
Marko Mikulicic 0:c0ecb8bf28eb 25479 *
Marko Mikulicic 0:c0ecb8bf28eb 25480 * l2:
Marko Mikulicic 0:c0ecb8bf28eb 25481 * <B2>
Marko Mikulicic 0:c0ecb8bf28eb 25482 *
Marko Mikulicic 0:c0ecb8bf28eb 25483 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25484 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25485 *
Marko Mikulicic 0:c0ecb8bf28eb 25486 * If the default case is missing we treat it as if had an empty body and
Marko Mikulicic 0:c0ecb8bf28eb 25487 * placed in last position (i.e. `dfl` label is replaced with `end`).
Marko Mikulicic 0:c0ecb8bf28eb 25488 *
Marko Mikulicic 0:c0ecb8bf28eb 25489 * Before emitting a case/default block (except the first one) we have to
Marko Mikulicic 0:c0ecb8bf28eb 25490 * drop the TOS resulting from evaluating the last expression
Marko Mikulicic 0:c0ecb8bf28eb 25491 */
Marko Mikulicic 0:c0ecb8bf28eb 25492 case AST_SWITCH: {
Marko Mikulicic 0:c0ecb8bf28eb 25493 bcode_off_t dfl_label, end_label;
Marko Mikulicic 0:c0ecb8bf28eb 25494 ast_off_t case_end, case_start;
Marko Mikulicic 0:c0ecb8bf28eb 25495 enum ast_tag case_tag;
Marko Mikulicic 0:c0ecb8bf28eb 25496 int i, has_default = 0, cases = 0;
Marko Mikulicic 0:c0ecb8bf28eb 25497
Marko Mikulicic 0:c0ecb8bf28eb 25498 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25499
Marko Mikulicic 0:c0ecb8bf28eb 25500 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_SWITCH);
Marko Mikulicic 0:c0ecb8bf28eb 25501
Marko Mikulicic 0:c0ecb8bf28eb 25502 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25503
Marko Mikulicic 0:c0ecb8bf28eb 25504 case_start = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25505 /* first pass: evaluate case expression and generate jump table */
Marko Mikulicic 0:c0ecb8bf28eb 25506 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25507 case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25508 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25509
Marko Mikulicic 0:c0ecb8bf28eb 25510 case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25511
Marko Mikulicic 0:c0ecb8bf28eb 25512 switch (case_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 25513 case AST_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 25514 /* default jump table entry must be the last one */
Marko Mikulicic 0:c0ecb8bf28eb 25515 break;
Marko Mikulicic 0:c0ecb8bf28eb 25516 case AST_CASE: {
Marko Mikulicic 0:c0ecb8bf28eb 25517 bcode_off_t case_label;
Marko Mikulicic 0:c0ecb8bf28eb 25518 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 25519 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25520 bcode_op(bbuilder, OP_EQ);
Marko Mikulicic 0:c0ecb8bf28eb 25521 case_label = bcode_op_target(bbuilder, OP_JMP_TRUE_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25522 cases++;
Marko Mikulicic 0:c0ecb8bf28eb 25523 mbuf_append(&case_labels, &case_label, sizeof(case_label));
Marko Mikulicic 0:c0ecb8bf28eb 25524 break;
Marko Mikulicic 0:c0ecb8bf28eb 25525 }
Marko Mikulicic 0:c0ecb8bf28eb 25526 default:
Marko Mikulicic 0:c0ecb8bf28eb 25527 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25528 }
Marko Mikulicic 0:c0ecb8bf28eb 25529 *ppos = case_end;
Marko Mikulicic 0:c0ecb8bf28eb 25530 }
Marko Mikulicic 0:c0ecb8bf28eb 25531
Marko Mikulicic 0:c0ecb8bf28eb 25532 /* jmp table epilogue: unconditional jump to default case */
Marko Mikulicic 0:c0ecb8bf28eb 25533 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25534 dfl_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25535
Marko Mikulicic 0:c0ecb8bf28eb 25536 *ppos = case_start;
Marko Mikulicic 0:c0ecb8bf28eb 25537 /* second pass: emit case bodies and patch jump table */
Marko Mikulicic 0:c0ecb8bf28eb 25538
Marko Mikulicic 0:c0ecb8bf28eb 25539 for (i = 0; *ppos < end;) {
Marko Mikulicic 0:c0ecb8bf28eb 25540 case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25541 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25542 assert(i <= cases);
Marko Mikulicic 0:c0ecb8bf28eb 25543
Marko Mikulicic 0:c0ecb8bf28eb 25544 case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25545
Marko Mikulicic 0:c0ecb8bf28eb 25546 switch (case_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 25547 case AST_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 25548 has_default = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25549 bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25550 V7_TRY(compile_stmts(bbuilder, a, ppos, case_end));
Marko Mikulicic 0:c0ecb8bf28eb 25551 break;
Marko Mikulicic 0:c0ecb8bf28eb 25552 case AST_CASE: {
Marko Mikulicic 0:c0ecb8bf28eb 25553 bcode_off_t case_label = ((bcode_off_t *) case_labels.buf)[i++];
Marko Mikulicic 0:c0ecb8bf28eb 25554 bcode_patch_target(bbuilder, case_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25555 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25556 V7_TRY(compile_stmts(bbuilder, a, ppos, case_end));
Marko Mikulicic 0:c0ecb8bf28eb 25557 break;
Marko Mikulicic 0:c0ecb8bf28eb 25558 }
Marko Mikulicic 0:c0ecb8bf28eb 25559 default:
Marko Mikulicic 0:c0ecb8bf28eb 25560 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25561 }
Marko Mikulicic 0:c0ecb8bf28eb 25562
Marko Mikulicic 0:c0ecb8bf28eb 25563 *ppos = case_end;
Marko Mikulicic 0:c0ecb8bf28eb 25564 }
Marko Mikulicic 0:c0ecb8bf28eb 25565 mbuf_free(&case_labels);
Marko Mikulicic 0:c0ecb8bf28eb 25566
Marko Mikulicic 0:c0ecb8bf28eb 25567 if (!has_default) {
Marko Mikulicic 0:c0ecb8bf28eb 25568 bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25569 }
Marko Mikulicic 0:c0ecb8bf28eb 25570
Marko Mikulicic 0:c0ecb8bf28eb 25571 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25572 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25573
Marko Mikulicic 0:c0ecb8bf28eb 25574 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25575 break;
Marko Mikulicic 0:c0ecb8bf28eb 25576 }
Marko Mikulicic 0:c0ecb8bf28eb 25577 /*
Marko Mikulicic 0:c0ecb8bf28eb 25578 * for(INIT,COND,IT) {
Marko Mikulicic 0:c0ecb8bf28eb 25579 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25580 * }
Marko Mikulicic 0:c0ecb8bf28eb 25581 *
Marko Mikulicic 0:c0ecb8bf28eb 25582 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25583 *
Marko Mikulicic 0:c0ecb8bf28eb 25584 * <INIT>
Marko Mikulicic 0:c0ecb8bf28eb 25585 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25586 * TRY_PUSH_LOOP end
Marko Mikulicic 0:c0ecb8bf28eb 25587 * JMP cond
Marko Mikulicic 0:c0ecb8bf28eb 25588 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25589 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25590 * next:
Marko Mikulicic 0:c0ecb8bf28eb 25591 * <IT>
Marko Mikulicic 0:c0ecb8bf28eb 25592 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25593 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 25594 * <COND>
Marko Mikulicic 0:c0ecb8bf28eb 25595 * JMP_TRUE body
Marko Mikulicic 0:c0ecb8bf28eb 25596 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25597 * JMP_IF_CONTINUE next
Marko Mikulicic 0:c0ecb8bf28eb 25598 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25599 *
Marko Mikulicic 0:c0ecb8bf28eb 25600 */
Marko Mikulicic 0:c0ecb8bf28eb 25601 case AST_FOR: {
Marko Mikulicic 0:c0ecb8bf28eb 25602 ast_off_t iter, body, lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 25603 bcode_off_t end_label, continue_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25604 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25605 body = ast_get_skip(a, pos_after_tag, AST_FOR_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25606
Marko Mikulicic 0:c0ecb8bf28eb 25607 lookahead = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25608 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25609 /*
Marko Mikulicic 0:c0ecb8bf28eb 25610 * Support for `var` declaration in INIT
Marko Mikulicic 0:c0ecb8bf28eb 25611 */
Marko Mikulicic 0:c0ecb8bf28eb 25612 if (tag == AST_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 25613 ast_off_t fvar_end;
Marko Mikulicic 0:c0ecb8bf28eb 25614 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 25615
Marko Mikulicic 0:c0ecb8bf28eb 25616 *ppos = lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 25617 fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25618
Marko Mikulicic 0:c0ecb8bf28eb 25619 /*
Marko Mikulicic 0:c0ecb8bf28eb 25620 * Iterate through all vars in the given `var` declaration: they are
Marko Mikulicic 0:c0ecb8bf28eb 25621 * just like assigments here
Marko Mikulicic 0:c0ecb8bf28eb 25622 */
Marko Mikulicic 0:c0ecb8bf28eb 25623 while (*ppos < fvar_end) {
Marko Mikulicic 0:c0ecb8bf28eb 25624 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25625 /* Only var declarations are allowed (not function declarations) */
Marko Mikulicic 0:c0ecb8bf28eb 25626 V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 25627 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25628 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25629
Marko Mikulicic 0:c0ecb8bf28eb 25630 /* Just like an assigment */
Marko Mikulicic 0:c0ecb8bf28eb 25631 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 25632
Marko Mikulicic 0:c0ecb8bf28eb 25633 /* INIT is stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 25634 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25635 }
Marko Mikulicic 0:c0ecb8bf28eb 25636 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25637 /* normal expression in INIT (not `var` declaration) */
Marko Mikulicic 0:c0ecb8bf28eb 25638 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25639 /* INIT is stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 25640 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25641 }
Marko Mikulicic 0:c0ecb8bf28eb 25642 cond = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25643 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25644 iter = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25645 *ppos = body;
Marko Mikulicic 0:c0ecb8bf28eb 25646
Marko Mikulicic 0:c0ecb8bf28eb 25647 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25648 cond_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25649 body_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25650 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25651
Marko Mikulicic 0:c0ecb8bf28eb 25652 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25653
Marko Mikulicic 0:c0ecb8bf28eb 25654 V7_TRY(compile_expr_builder(bbuilder, a, &iter));
Marko Mikulicic 0:c0ecb8bf28eb 25655 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25656
Marko Mikulicic 0:c0ecb8bf28eb 25657 bcode_patch_target(bbuilder, cond_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25658
Marko Mikulicic 0:c0ecb8bf28eb 25659 /*
Marko Mikulicic 0:c0ecb8bf28eb 25660 * Handle for(INIT;;ITER)
Marko Mikulicic 0:c0ecb8bf28eb 25661 */
Marko Mikulicic 0:c0ecb8bf28eb 25662 lookahead = cond;
Marko Mikulicic 0:c0ecb8bf28eb 25663 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25664 if (tag == AST_NOP) {
Marko Mikulicic 0:c0ecb8bf28eb 25665 bcode_op(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25666 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25667 V7_TRY(compile_expr_builder(bbuilder, a, &cond));
Marko Mikulicic 0:c0ecb8bf28eb 25668 bcode_op(bbuilder, OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25669 }
Marko Mikulicic 0:c0ecb8bf28eb 25670 body_label = bcode_add_target(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25671 bcode_patch_target(bbuilder, body_label, body_target);
Marko Mikulicic 0:c0ecb8bf28eb 25672 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25673
Marko Mikulicic 0:c0ecb8bf28eb 25674 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25675 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25676
Marko Mikulicic 0:c0ecb8bf28eb 25677 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25678
Marko Mikulicic 0:c0ecb8bf28eb 25679 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25680 break;
Marko Mikulicic 0:c0ecb8bf28eb 25681 }
Marko Mikulicic 0:c0ecb8bf28eb 25682 /*
Marko Mikulicic 0:c0ecb8bf28eb 25683 * for(I in O) {
Marko Mikulicic 0:c0ecb8bf28eb 25684 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25685 * }
Marko Mikulicic 0:c0ecb8bf28eb 25686 *
Marko Mikulicic 0:c0ecb8bf28eb 25687 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25688 *
Marko Mikulicic 0:c0ecb8bf28eb 25689 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 25690 * <O>
Marko Mikulicic 0:c0ecb8bf28eb 25691 * SWAP
Marko Mikulicic 0:c0ecb8bf28eb 25692 * STASH
Marko Mikulicic 0:c0ecb8bf28eb 25693 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25694 * PUSH_PROP_ITER_CTX # push initial iteration context
Marko Mikulicic 0:c0ecb8bf28eb 25695 * TRY_PUSH_LOOP brend
Marko Mikulicic 0:c0ecb8bf28eb 25696 * loop:
Marko Mikulicic 0:c0ecb8bf28eb 25697 * NEXT_PROP
Marko Mikulicic 0:c0ecb8bf28eb 25698 * JMP_FALSE end
Marko Mikulicic 0:c0ecb8bf28eb 25699 * SET_VAR <I>
Marko Mikulicic 0:c0ecb8bf28eb 25700 * UNSTASH
Marko Mikulicic 0:c0ecb8bf28eb 25701 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25702 * next:
Marko Mikulicic 0:c0ecb8bf28eb 25703 * STASH
Marko Mikulicic 0:c0ecb8bf28eb 25704 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25705 * JMP loop
Marko Mikulicic 0:c0ecb8bf28eb 25706 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25707 * UNSTASH
Marko Mikulicic 0:c0ecb8bf28eb 25708 * JMP try_pop:
Marko Mikulicic 0:c0ecb8bf28eb 25709 * brend:
Marko Mikulicic 0:c0ecb8bf28eb 25710 * # got here after a `break` or `continue` from a loop body:
Marko Mikulicic 0:c0ecb8bf28eb 25711 * JMP_IF_CONTINUE next
Marko Mikulicic 0:c0ecb8bf28eb 25712 *
Marko Mikulicic 0:c0ecb8bf28eb 25713 * # we're not going to `continue`, so, need to remove an
Marko Mikulicic 0:c0ecb8bf28eb 25714 * # extra stuff that was needed for the NEXT_PROP
Marko Mikulicic 0:c0ecb8bf28eb 25715 *
Marko Mikulicic 0:c0ecb8bf28eb 25716 * SWAP_DROP # drop iteration context
Marko Mikulicic 0:c0ecb8bf28eb 25717 * SWAP_DROP # drop <O>
Marko Mikulicic 0:c0ecb8bf28eb 25718 * SWAP_DROP # drop the value preceding the loop
Marko Mikulicic 0:c0ecb8bf28eb 25719 * try_pop:
Marko Mikulicic 0:c0ecb8bf28eb 25720 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25721 *
Marko Mikulicic 0:c0ecb8bf28eb 25722 */
Marko Mikulicic 0:c0ecb8bf28eb 25723 case AST_FOR_IN: {
Marko Mikulicic 0:c0ecb8bf28eb 25724 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 25725 bcode_off_t loop_label, loop_target, end_label, brend_label,
Marko Mikulicic 0:c0ecb8bf28eb 25726 continue_label, pop_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25727 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25728
Marko Mikulicic 0:c0ecb8bf28eb 25729 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25730 /* TODO(mkm) accept any l-value */
Marko Mikulicic 0:c0ecb8bf28eb 25731 if (tag == AST_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 25732 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25733 V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 25734 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25735 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25736 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25737 V7_CHECK_INTERNAL(tag == AST_IDENT);
Marko Mikulicic 0:c0ecb8bf28eb 25738 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25739 }
Marko Mikulicic 0:c0ecb8bf28eb 25740
Marko Mikulicic 0:c0ecb8bf28eb 25741 /*
Marko Mikulicic 0:c0ecb8bf28eb 25742 * preserve previous statement value.
Marko Mikulicic 0:c0ecb8bf28eb 25743 * We need to feed the previous value into the stash
Marko Mikulicic 0:c0ecb8bf28eb 25744 * because it's required for the loop steady state.
Marko Mikulicic 0:c0ecb8bf28eb 25745 *
Marko Mikulicic 0:c0ecb8bf28eb 25746 * The stash register is required to simplify the steady state stack
Marko Mikulicic 0:c0ecb8bf28eb 25747 * management, in particular the removal of value in 3rd position in case
Marko Mikulicic 0:c0ecb8bf28eb 25748 * a of not taken exit.
Marko Mikulicic 0:c0ecb8bf28eb 25749 *
Marko Mikulicic 0:c0ecb8bf28eb 25750 * TODO(mkm): consider having a stash OP that moves a value to the stash
Marko Mikulicic 0:c0ecb8bf28eb 25751 * register instead of copying it. The current behaviour has been
Marko Mikulicic 0:c0ecb8bf28eb 25752 * optimized for the `assign` use case which seems more common.
Marko Mikulicic 0:c0ecb8bf28eb 25753 */
Marko Mikulicic 0:c0ecb8bf28eb 25754 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 25755 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25756 bcode_op(bbuilder, OP_SWAP);
Marko Mikulicic 0:c0ecb8bf28eb 25757 bcode_op(bbuilder, OP_STASH);
Marko Mikulicic 0:c0ecb8bf28eb 25758 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25759
Marko Mikulicic 0:c0ecb8bf28eb 25760 /*
Marko Mikulicic 0:c0ecb8bf28eb 25761 * OP_NEXT_PROP needs the iteration context, let's push the initial one.
Marko Mikulicic 0:c0ecb8bf28eb 25762 */
Marko Mikulicic 0:c0ecb8bf28eb 25763 bcode_op(bbuilder, OP_PUSH_PROP_ITER_CTX);
Marko Mikulicic 0:c0ecb8bf28eb 25764
Marko Mikulicic 0:c0ecb8bf28eb 25765 brend_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25766
Marko Mikulicic 0:c0ecb8bf28eb 25767 /* loop: */
Marko Mikulicic 0:c0ecb8bf28eb 25768 loop_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25769
Marko Mikulicic 0:c0ecb8bf28eb 25770 /*
Marko Mikulicic 0:c0ecb8bf28eb 25771 * The loop stead state begins with the following stack layout:
Marko Mikulicic 0:c0ecb8bf28eb 25772 * `( S:v o h )`
Marko Mikulicic 0:c0ecb8bf28eb 25773 */
Marko Mikulicic 0:c0ecb8bf28eb 25774
Marko Mikulicic 0:c0ecb8bf28eb 25775 bcode_op(bbuilder, OP_NEXT_PROP);
Marko Mikulicic 0:c0ecb8bf28eb 25776 end_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 25777 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 25778
Marko Mikulicic 0:c0ecb8bf28eb 25779 /*
Marko Mikulicic 0:c0ecb8bf28eb 25780 * The stash register contains the value of the previous statement,
Marko Mikulicic 0:c0ecb8bf28eb 25781 * being it the statement before the for..in statement or
Marko Mikulicic 0:c0ecb8bf28eb 25782 * the previous iteration. We move it to the data stack. It will
Marko Mikulicic 0:c0ecb8bf28eb 25783 * be replaced by the values of the body statements as usual.
Marko Mikulicic 0:c0ecb8bf28eb 25784 */
Marko Mikulicic 0:c0ecb8bf28eb 25785 bcode_op(bbuilder, OP_UNSTASH);
Marko Mikulicic 0:c0ecb8bf28eb 25786
Marko Mikulicic 0:c0ecb8bf28eb 25787 /*
Marko Mikulicic 0:c0ecb8bf28eb 25788 * This node is always a NOP, for compatibility
Marko Mikulicic 0:c0ecb8bf28eb 25789 * with the layout of the AST_FOR node.
Marko Mikulicic 0:c0ecb8bf28eb 25790 */
Marko Mikulicic 0:c0ecb8bf28eb 25791 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25792
Marko Mikulicic 0:c0ecb8bf28eb 25793 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25794
Marko Mikulicic 0:c0ecb8bf28eb 25795 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25796
Marko Mikulicic 0:c0ecb8bf28eb 25797 /*
Marko Mikulicic 0:c0ecb8bf28eb 25798 * Save the last body statement. If next evaluation of NEXT_PROP returns
Marko Mikulicic 0:c0ecb8bf28eb 25799 * false, we'll unstash it.
Marko Mikulicic 0:c0ecb8bf28eb 25800 */
Marko Mikulicic 0:c0ecb8bf28eb 25801 bcode_op(bbuilder, OP_STASH);
Marko Mikulicic 0:c0ecb8bf28eb 25802 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25803
Marko Mikulicic 0:c0ecb8bf28eb 25804 loop_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25805 bcode_patch_target(bbuilder, loop_label, loop_target);
Marko Mikulicic 0:c0ecb8bf28eb 25806
Marko Mikulicic 0:c0ecb8bf28eb 25807 /* end: */
Marko Mikulicic 0:c0ecb8bf28eb 25808 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25809 bcode_op(bbuilder, OP_UNSTASH);
Marko Mikulicic 0:c0ecb8bf28eb 25810
Marko Mikulicic 0:c0ecb8bf28eb 25811 pop_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25812
Marko Mikulicic 0:c0ecb8bf28eb 25813 /* brend: */
Marko Mikulicic 0:c0ecb8bf28eb 25814 bcode_patch_target(bbuilder, brend_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25815
Marko Mikulicic 0:c0ecb8bf28eb 25816 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25817 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25818
Marko Mikulicic 0:c0ecb8bf28eb 25819 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25820 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25821 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25822
Marko Mikulicic 0:c0ecb8bf28eb 25823 /* try_pop: */
Marko Mikulicic 0:c0ecb8bf28eb 25824 bcode_patch_target(bbuilder, pop_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25825
Marko Mikulicic 0:c0ecb8bf28eb 25826 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25827
Marko Mikulicic 0:c0ecb8bf28eb 25828 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25829 break;
Marko Mikulicic 0:c0ecb8bf28eb 25830 }
Marko Mikulicic 0:c0ecb8bf28eb 25831 /*
Marko Mikulicic 0:c0ecb8bf28eb 25832 * do {
Marko Mikulicic 0:c0ecb8bf28eb 25833 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25834 * } while(COND);
Marko Mikulicic 0:c0ecb8bf28eb 25835 *
Marko Mikulicic 0:c0ecb8bf28eb 25836 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25837 *
Marko Mikulicic 0:c0ecb8bf28eb 25838 * TRY_PUSH_LOOP end
Marko Mikulicic 0:c0ecb8bf28eb 25839 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25840 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25841 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 25842 * <COND>
Marko Mikulicic 0:c0ecb8bf28eb 25843 * JMP_TRUE body
Marko Mikulicic 0:c0ecb8bf28eb 25844 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25845 * JMP_IF_CONTINUE cond
Marko Mikulicic 0:c0ecb8bf28eb 25846 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25847 *
Marko Mikulicic 0:c0ecb8bf28eb 25848 */
Marko Mikulicic 0:c0ecb8bf28eb 25849 case AST_DOWHILE: {
Marko Mikulicic 0:c0ecb8bf28eb 25850 bcode_off_t end_label, continue_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25851 end = ast_get_skip(a, pos_after_tag, AST_DO_WHILE_COND_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25852 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25853 body_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25854 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25855
Marko Mikulicic 0:c0ecb8bf28eb 25856 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25857 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25858 body_label = bcode_op_target(bbuilder, OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25859 bcode_patch_target(bbuilder, body_label, body_target);
Marko Mikulicic 0:c0ecb8bf28eb 25860
Marko Mikulicic 0:c0ecb8bf28eb 25861 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25862 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25863 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25864 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25865
Marko Mikulicic 0:c0ecb8bf28eb 25866 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25867 break;
Marko Mikulicic 0:c0ecb8bf28eb 25868 }
Marko Mikulicic 0:c0ecb8bf28eb 25869 case AST_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 25870 /*
Marko Mikulicic 0:c0ecb8bf28eb 25871 * Var decls are hoisted when the function frame is created. Vars
Marko Mikulicic 0:c0ecb8bf28eb 25872 * declared inside a `with` or `catch` block belong to the function
Marko Mikulicic 0:c0ecb8bf28eb 25873 * lexical scope, and although those clauses create an inner frame
Marko Mikulicic 0:c0ecb8bf28eb 25874 * no new variables should be created in it. A var decl thus
Marko Mikulicic 0:c0ecb8bf28eb 25875 * behaves as a normal assignment at runtime.
Marko Mikulicic 0:c0ecb8bf28eb 25876 */
Marko Mikulicic 0:c0ecb8bf28eb 25877 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 25878 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25879 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25880 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25881 if (tag == AST_FUNC_DECL) {
Marko Mikulicic 0:c0ecb8bf28eb 25882 /*
Marko Mikulicic 0:c0ecb8bf28eb 25883 * function declarations are already set during hoisting (see
Marko Mikulicic 0:c0ecb8bf28eb 25884 * `compile_local_vars()`), so, skip it.
Marko Mikulicic 0:c0ecb8bf28eb 25885 *
Marko Mikulicic 0:c0ecb8bf28eb 25886 * Plus, they are stack-neutral, so don't forget to set
Marko Mikulicic 0:c0ecb8bf28eb 25887 * `is_stack_neutral`.
Marko Mikulicic 0:c0ecb8bf28eb 25888 */
Marko Mikulicic 0:c0ecb8bf28eb 25889 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25890 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25891 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25892 /*
Marko Mikulicic 0:c0ecb8bf28eb 25893 * compile `var` declaration: basically it looks similar to an
Marko Mikulicic 0:c0ecb8bf28eb 25894 * assignment, but it differs from an assignment is that it's
Marko Mikulicic 0:c0ecb8bf28eb 25895 * stack-neutral: `1; var a = 5;` yields `1`, not `5`.
Marko Mikulicic 0:c0ecb8bf28eb 25896 */
Marko Mikulicic 0:c0ecb8bf28eb 25897 V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 25898 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25899 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25900 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 25901
Marko Mikulicic 0:c0ecb8bf28eb 25902 /* `var` declaration is stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 25903 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25904 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25905 }
Marko Mikulicic 0:c0ecb8bf28eb 25906 }
Marko Mikulicic 0:c0ecb8bf28eb 25907 break;
Marko Mikulicic 0:c0ecb8bf28eb 25908 }
Marko Mikulicic 0:c0ecb8bf28eb 25909 case AST_RETURN:
Marko Mikulicic 0:c0ecb8bf28eb 25910 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25911 bcode_op(bbuilder, OP_RET);
Marko Mikulicic 0:c0ecb8bf28eb 25912 break;
Marko Mikulicic 0:c0ecb8bf28eb 25913 case AST_VALUE_RETURN:
Marko Mikulicic 0:c0ecb8bf28eb 25914 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25915 bcode_op(bbuilder, OP_RET);
Marko Mikulicic 0:c0ecb8bf28eb 25916 break;
Marko Mikulicic 0:c0ecb8bf28eb 25917 default:
Marko Mikulicic 0:c0ecb8bf28eb 25918 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25919 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25920 }
Marko Mikulicic 0:c0ecb8bf28eb 25921
Marko Mikulicic 0:c0ecb8bf28eb 25922 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25923 mbuf_free(&case_labels);
Marko Mikulicic 0:c0ecb8bf28eb 25924 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25925 }
Marko Mikulicic 0:c0ecb8bf28eb 25926
Marko Mikulicic 0:c0ecb8bf28eb 25927 static enum v7_err compile_body(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 25928 ast_off_t start, ast_off_t end, ast_off_t body,
Marko Mikulicic 0:c0ecb8bf28eb 25929 ast_off_t fvar, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 25930 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25931 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 25932
Marko Mikulicic 0:c0ecb8bf28eb 25933 #ifndef V7_FORCE_STRICT_MODE
Marko Mikulicic 0:c0ecb8bf28eb 25934 /* check 'use strict' */
Marko Mikulicic 0:c0ecb8bf28eb 25935 if (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25936 ast_off_t tmp_pos = body;
Marko Mikulicic 0:c0ecb8bf28eb 25937 if (fetch_tag(v7, bbuilder, a, &tmp_pos, NULL) == AST_USE_STRICT) {
Marko Mikulicic 0:c0ecb8bf28eb 25938 bbuilder->bcode->strict_mode = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25939 /* move `body` offset, effectively removing `AST_USE_STRICT` from it */
Marko Mikulicic 0:c0ecb8bf28eb 25940 body = tmp_pos;
Marko Mikulicic 0:c0ecb8bf28eb 25941 }
Marko Mikulicic 0:c0ecb8bf28eb 25942 }
Marko Mikulicic 0:c0ecb8bf28eb 25943 #endif
Marko Mikulicic 0:c0ecb8bf28eb 25944
Marko Mikulicic 0:c0ecb8bf28eb 25945 /* put initial value for the function body execution */
Marko Mikulicic 0:c0ecb8bf28eb 25946 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25947
Marko Mikulicic 0:c0ecb8bf28eb 25948 /*
Marko Mikulicic 0:c0ecb8bf28eb 25949 * populate `bcode->ops` with function's local variable names. Note that we
Marko Mikulicic 0:c0ecb8bf28eb 25950 * should do this *after* `OP_PUSH_UNDEFINED`, since `compile_local_vars`
Marko Mikulicic 0:c0ecb8bf28eb 25951 * emits code that assigns the hoisted functions to local variables, and
Marko Mikulicic 0:c0ecb8bf28eb 25952 * those statements assume that the stack contains `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 25953 */
Marko Mikulicic 0:c0ecb8bf28eb 25954 V7_TRY(compile_local_vars(bbuilder, a, start, fvar));
Marko Mikulicic 0:c0ecb8bf28eb 25955
Marko Mikulicic 0:c0ecb8bf28eb 25956 /* compile body */
Marko Mikulicic 0:c0ecb8bf28eb 25957 *ppos = body;
Marko Mikulicic 0:c0ecb8bf28eb 25958 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25959
Marko Mikulicic 0:c0ecb8bf28eb 25960 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25961 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25962 }
Marko Mikulicic 0:c0ecb8bf28eb 25963
Marko Mikulicic 0:c0ecb8bf28eb 25964 /*
Marko Mikulicic 0:c0ecb8bf28eb 25965 * Compiles a given script and populates a bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 25966 * The AST must start with an AST_SCRIPT node.
Marko Mikulicic 0:c0ecb8bf28eb 25967 */
Marko Mikulicic 0:c0ecb8bf28eb 25968 V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 25969 struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 25970 ast_off_t pos_after_tag, end, fvar, pos = 0;
Marko Mikulicic 0:c0ecb8bf28eb 25971 int saved_line_no = v7->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 25972 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25973 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 25974 enum ast_tag tag;
Marko Mikulicic 0:c0ecb8bf28eb 25975
Marko Mikulicic 0:c0ecb8bf28eb 25976 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25977 v7->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25978
Marko Mikulicic 0:c0ecb8bf28eb 25979 tag = fetch_tag(v7, &bbuilder, a, &pos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25980
Marko Mikulicic 0:c0ecb8bf28eb 25981 /* first tag should always be AST_SCRIPT */
Marko Mikulicic 0:c0ecb8bf28eb 25982 assert(tag == AST_SCRIPT);
Marko Mikulicic 0:c0ecb8bf28eb 25983 (void) tag;
Marko Mikulicic 0:c0ecb8bf28eb 25984
Marko Mikulicic 0:c0ecb8bf28eb 25985 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25986 fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25987
Marko Mikulicic 0:c0ecb8bf28eb 25988 V7_TRY(compile_body(&bbuilder, a, pos_after_tag - 1, end, pos /* body */,
Marko Mikulicic 0:c0ecb8bf28eb 25989 fvar, &pos));
Marko Mikulicic 0:c0ecb8bf28eb 25990
Marko Mikulicic 0:c0ecb8bf28eb 25991 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25992
Marko Mikulicic 0:c0ecb8bf28eb 25993 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25994
Marko Mikulicic 0:c0ecb8bf28eb 25995 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 25996 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 25997 fprintf(stderr, "--- script ---\n");
Marko Mikulicic 0:c0ecb8bf28eb 25998 dump_bcode(v7, stderr, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25999 }
Marko Mikulicic 0:c0ecb8bf28eb 26000 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26001
Marko Mikulicic 0:c0ecb8bf28eb 26002 v7->line_no = saved_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 26003
Marko Mikulicic 0:c0ecb8bf28eb 26004 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26005 }
Marko Mikulicic 0:c0ecb8bf28eb 26006
Marko Mikulicic 0:c0ecb8bf28eb 26007 /*
Marko Mikulicic 0:c0ecb8bf28eb 26008 * Compiles a given function and populates a bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 26009 * The AST must contain an AST_FUNC node at offset ast_off.
Marko Mikulicic 0:c0ecb8bf28eb 26010 */
Marko Mikulicic 0:c0ecb8bf28eb 26011 V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 26012 ast_off_t *ppos, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 26013 ast_off_t pos_after_tag, start, end, body, fvar;
Marko Mikulicic 0:c0ecb8bf28eb 26014 const char *name;
Marko Mikulicic 0:c0ecb8bf28eb 26015 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 26016 size_t args_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 26017 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26018 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 26019 enum ast_tag tag;
Marko Mikulicic 0:c0ecb8bf28eb 26020 size_t names_end = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26021 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 26022 tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 26023 start = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 26024
Marko Mikulicic 0:c0ecb8bf28eb 26025 (void) tag;
Marko Mikulicic 0:c0ecb8bf28eb 26026 assert(tag == AST_FUNC);
Marko Mikulicic 0:c0ecb8bf28eb 26027 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 26028 body = ast_get_skip(a, pos_after_tag, AST_FUNC_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 26029 fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 26030
Marko Mikulicic 0:c0ecb8bf28eb 26031 /* retrieve function name */
Marko Mikulicic 0:c0ecb8bf28eb 26032 tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 26033 if (tag == AST_IDENT) {
Marko Mikulicic 0:c0ecb8bf28eb 26034 /* function name is provided */
Marko Mikulicic 0:c0ecb8bf28eb 26035 name = ast_get_inlined_data(a, pos_after_tag, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 26036 V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 26037 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26038 /* no name: anonymous function */
Marko Mikulicic 0:c0ecb8bf28eb 26039 V7_TRY(bcode_add_name(&bbuilder, "", 0, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 26040 }
Marko Mikulicic 0:c0ecb8bf28eb 26041
Marko Mikulicic 0:c0ecb8bf28eb 26042 /* retrieve function's argument names */
Marko Mikulicic 0:c0ecb8bf28eb 26043 for (args_cnt = 0; *ppos < body; args_cnt++) {
Marko Mikulicic 0:c0ecb8bf28eb 26044 if (args_cnt > V7_ARGS_CNT_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 26045 /* too many arguments */
Marko Mikulicic 0:c0ecb8bf28eb 26046 rcode = v7_throwf(v7, SYNTAX_ERROR, "Too many arguments");
Marko Mikulicic 0:c0ecb8bf28eb 26047 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 26048 }
Marko Mikulicic 0:c0ecb8bf28eb 26049
Marko Mikulicic 0:c0ecb8bf28eb 26050 tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 26051 /*
Marko Mikulicic 0:c0ecb8bf28eb 26052 * TODO(dfrank): it's not actually an internal error, we get here if
Marko Mikulicic 0:c0ecb8bf28eb 26053 * we compile e.g. the following: (function(1){})
Marko Mikulicic 0:c0ecb8bf28eb 26054 */
Marko Mikulicic 0:c0ecb8bf28eb 26055 V7_CHECK_INTERNAL(tag == AST_IDENT);
Marko Mikulicic 0:c0ecb8bf28eb 26056 name = ast_get_inlined_data(a, pos_after_tag, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 26057 V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 26058 }
Marko Mikulicic 0:c0ecb8bf28eb 26059
Marko Mikulicic 0:c0ecb8bf28eb 26060 bcode->args_cnt = args_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 26061 bcode->func_name_present = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26062
Marko Mikulicic 0:c0ecb8bf28eb 26063 V7_TRY(compile_body(&bbuilder, a, start, end, body, fvar, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 26064
Marko Mikulicic 0:c0ecb8bf28eb 26065 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26066 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 26067
Marko Mikulicic 0:c0ecb8bf28eb 26068 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 26069 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26070 fprintf(stderr, "--- function ---\n");
Marko Mikulicic 0:c0ecb8bf28eb 26071 dump_bcode(v7, stderr, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 26072 }
Marko Mikulicic 0:c0ecb8bf28eb 26073 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26074
Marko Mikulicic 0:c0ecb8bf28eb 26075 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26076 }
Marko Mikulicic 0:c0ecb8bf28eb 26077
Marko Mikulicic 0:c0ecb8bf28eb 26078 V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 26079 ast_off_t *ppos, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 26080 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26081 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 26082 int saved_line_no = v7->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 26083
Marko Mikulicic 0:c0ecb8bf28eb 26084 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 26085 v7->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26086
Marko Mikulicic 0:c0ecb8bf28eb 26087 rcode = compile_expr_builder(&bbuilder, a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 26088
Marko Mikulicic 0:c0ecb8bf28eb 26089 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 26090 v7->line_no = saved_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 26091 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26092 }
Marko Mikulicic 0:c0ecb8bf28eb 26093
Marko Mikulicic 0:c0ecb8bf28eb 26094 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 26095 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 26096 #line 1 "v7/src/stdlib.c"
Marko Mikulicic 0:c0ecb8bf28eb 26097 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26098 /*
Marko Mikulicic 0:c0ecb8bf28eb 26099 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 26100 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 26101 */
Marko Mikulicic 0:c0ecb8bf28eb 26102
Marko Mikulicic 0:c0ecb8bf28eb 26103 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26104
Marko Mikulicic 0:c0ecb8bf28eb 26105 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26106 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26107 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26108 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26109 /* Amalgamated: #include "v7/src/stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26110 /* Amalgamated: #include "v7/src/std_array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26111 /* Amalgamated: #include "v7/src/std_boolean.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26112 /* Amalgamated: #include "v7/src/std_date.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26113 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26114 /* Amalgamated: #include "v7/src/std_function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26115 /* Amalgamated: #include "v7/src/std_json.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26116 /* Amalgamated: #include "v7/src/std_math.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26117 /* Amalgamated: #include "v7/src/std_number.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26118 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26119 /* Amalgamated: #include "v7/src/std_regex.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26120 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26121 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26122 /* Amalgamated: #include "v7/src/js_stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26123 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26124 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26125 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26126 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26127
Marko Mikulicic 0:c0ecb8bf28eb 26128 #ifdef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26129 void print_str(const char *str);
Marko Mikulicic 0:c0ecb8bf28eb 26130 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26131
Marko Mikulicic 0:c0ecb8bf28eb 26132 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26133 V7_PRIVATE enum v7_err Std_print(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26134 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26135 int i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26136 val_t v;
Marko Mikulicic 0:c0ecb8bf28eb 26137
Marko Mikulicic 0:c0ecb8bf28eb 26138 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 26139
Marko Mikulicic 0:c0ecb8bf28eb 26140 for (i = 0; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 26141 v = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 26142 if (v7_is_string(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 26143 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 26144 const char *s = v7_get_string(v7, &v, &n);
Marko Mikulicic 0:c0ecb8bf28eb 26145 printf("%.*s", (int) n, s);
Marko Mikulicic 0:c0ecb8bf28eb 26146 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26147 v7_print(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 26148 }
Marko Mikulicic 0:c0ecb8bf28eb 26149 printf(" ");
Marko Mikulicic 0:c0ecb8bf28eb 26150 }
Marko Mikulicic 0:c0ecb8bf28eb 26151 printf(ENDL);
Marko Mikulicic 0:c0ecb8bf28eb 26152
Marko Mikulicic 0:c0ecb8bf28eb 26153 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26154 }
Marko Mikulicic 0:c0ecb8bf28eb 26155
Marko Mikulicic 0:c0ecb8bf28eb 26156 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26157 V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 26158 int is_json, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26159 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26160 char buf[100], *p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 26161 struct v7_exec_opts opts;
Marko Mikulicic 0:c0ecb8bf28eb 26162 memset(&opts, 0x00, sizeof(opts));
Marko Mikulicic 0:c0ecb8bf28eb 26163 opts.filename = "Eval'd code";
Marko Mikulicic 0:c0ecb8bf28eb 26164
Marko Mikulicic 0:c0ecb8bf28eb 26165 if (arg != V7_UNDEFINED) {
Marko Mikulicic 0:c0ecb8bf28eb 26166 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 26167 rcode = to_string(v7, arg, NULL, buf, sizeof(buf), &len);
Marko Mikulicic 0:c0ecb8bf28eb 26168 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26169 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26170 }
Marko Mikulicic 0:c0ecb8bf28eb 26171
Marko Mikulicic 0:c0ecb8bf28eb 26172 /* Fit null terminating byte and quotes */
Marko Mikulicic 0:c0ecb8bf28eb 26173 if (len >= sizeof(buf) - 2) {
Marko Mikulicic 0:c0ecb8bf28eb 26174 /* Buffer is not large enough. Allocate a bigger one */
Marko Mikulicic 0:c0ecb8bf28eb 26175 p = (char *) malloc(len + 3);
Marko Mikulicic 0:c0ecb8bf28eb 26176 rcode = to_string(v7, arg, NULL, p, len + 2, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26177 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26178 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26179 }
Marko Mikulicic 0:c0ecb8bf28eb 26180 }
Marko Mikulicic 0:c0ecb8bf28eb 26181
Marko Mikulicic 0:c0ecb8bf28eb 26182 v7_set_gc_enabled(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26183 if (is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 26184 opts.is_json = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26185 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26186 opts.this_obj = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 26187 }
Marko Mikulicic 0:c0ecb8bf28eb 26188 rcode = v7_exec_opt(v7, p, &opts, res);
Marko Mikulicic 0:c0ecb8bf28eb 26189 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26190 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26191 }
Marko Mikulicic 0:c0ecb8bf28eb 26192 }
Marko Mikulicic 0:c0ecb8bf28eb 26193
Marko Mikulicic 0:c0ecb8bf28eb 26194 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26195 if (p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 26196 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 26197 }
Marko Mikulicic 0:c0ecb8bf28eb 26198
Marko Mikulicic 0:c0ecb8bf28eb 26199 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26200 }
Marko Mikulicic 0:c0ecb8bf28eb 26201
Marko Mikulicic 0:c0ecb8bf28eb 26202 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26203 V7_PRIVATE enum v7_err Std_eval(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26204 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26205 v7_val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 26206 return std_eval(v7, arg, this_obj, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 26207 }
Marko Mikulicic 0:c0ecb8bf28eb 26208
Marko Mikulicic 0:c0ecb8bf28eb 26209 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26210 V7_PRIVATE enum v7_err Std_parseInt(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26211 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26212 v7_val_t arg0 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 26213 v7_val_t arg1 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 26214 long sign = 1, base, n;
Marko Mikulicic 0:c0ecb8bf28eb 26215 char buf[20], *p = buf, *end;
Marko Mikulicic 0:c0ecb8bf28eb 26216
Marko Mikulicic 0:c0ecb8bf28eb 26217 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26218
Marko Mikulicic 0:c0ecb8bf28eb 26219 arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 26220 arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26221
Marko Mikulicic 0:c0ecb8bf28eb 26222 rcode = to_string(v7, arg0, &arg0, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26223 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26224 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26225 }
Marko Mikulicic 0:c0ecb8bf28eb 26226
Marko Mikulicic 0:c0ecb8bf28eb 26227 rcode = to_number_v(v7, arg1, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 26228 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26229 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26230 }
Marko Mikulicic 0:c0ecb8bf28eb 26231
Marko Mikulicic 0:c0ecb8bf28eb 26232 if (is_finite(v7, arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 26233 base = v7_get_double(v7, arg1);
Marko Mikulicic 0:c0ecb8bf28eb 26234 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26235 base = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26236 }
Marko Mikulicic 0:c0ecb8bf28eb 26237
Marko Mikulicic 0:c0ecb8bf28eb 26238 if (base == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 26239 base = 10;
Marko Mikulicic 0:c0ecb8bf28eb 26240 }
Marko Mikulicic 0:c0ecb8bf28eb 26241
Marko Mikulicic 0:c0ecb8bf28eb 26242 if (base < 2 || base > 36) {
Marko Mikulicic 0:c0ecb8bf28eb 26243 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26244 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26245 }
Marko Mikulicic 0:c0ecb8bf28eb 26246
Marko Mikulicic 0:c0ecb8bf28eb 26247 {
Marko Mikulicic 0:c0ecb8bf28eb 26248 size_t str_len;
Marko Mikulicic 0:c0ecb8bf28eb 26249 p = (char *) v7_get_string(v7, &arg0, &str_len);
Marko Mikulicic 0:c0ecb8bf28eb 26250 }
Marko Mikulicic 0:c0ecb8bf28eb 26251
Marko Mikulicic 0:c0ecb8bf28eb 26252 /* Strip leading whitespaces */
Marko Mikulicic 0:c0ecb8bf28eb 26253 while (*p != '\0' && isspace(*(unsigned char *) p)) {
Marko Mikulicic 0:c0ecb8bf28eb 26254 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26255 }
Marko Mikulicic 0:c0ecb8bf28eb 26256
Marko Mikulicic 0:c0ecb8bf28eb 26257 if (*p == '+') {
Marko Mikulicic 0:c0ecb8bf28eb 26258 sign = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26259 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26260 } else if (*p == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 26261 sign = -1;
Marko Mikulicic 0:c0ecb8bf28eb 26262 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26263 }
Marko Mikulicic 0:c0ecb8bf28eb 26264
Marko Mikulicic 0:c0ecb8bf28eb 26265 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
Marko Mikulicic 0:c0ecb8bf28eb 26266 base = 16;
Marko Mikulicic 0:c0ecb8bf28eb 26267 p += 2;
Marko Mikulicic 0:c0ecb8bf28eb 26268 }
Marko Mikulicic 0:c0ecb8bf28eb 26269
Marko Mikulicic 0:c0ecb8bf28eb 26270 n = strtol(p, &end, base);
Marko Mikulicic 0:c0ecb8bf28eb 26271
Marko Mikulicic 0:c0ecb8bf28eb 26272 *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, n * sign);
Marko Mikulicic 0:c0ecb8bf28eb 26273
Marko Mikulicic 0:c0ecb8bf28eb 26274 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26275 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26276 }
Marko Mikulicic 0:c0ecb8bf28eb 26277
Marko Mikulicic 0:c0ecb8bf28eb 26278 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26279 V7_PRIVATE enum v7_err Std_parseFloat(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26280 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26281 v7_val_t arg0 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 26282 char buf[20], *p = buf, *end;
Marko Mikulicic 0:c0ecb8bf28eb 26283 double result;
Marko Mikulicic 0:c0ecb8bf28eb 26284
Marko Mikulicic 0:c0ecb8bf28eb 26285 rcode = to_primitive(v7, v7_arg(v7, 0), V7_TO_PRIMITIVE_HINT_NUMBER, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 26286 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26287 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26288 }
Marko Mikulicic 0:c0ecb8bf28eb 26289
Marko Mikulicic 0:c0ecb8bf28eb 26290 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 26291 size_t str_len;
Marko Mikulicic 0:c0ecb8bf28eb 26292 p = (char *) v7_get_string(v7, &arg0, &str_len);
Marko Mikulicic 0:c0ecb8bf28eb 26293 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26294 rcode = to_string(v7, arg0, NULL, buf, sizeof(buf), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26295 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26296 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26297 }
Marko Mikulicic 0:c0ecb8bf28eb 26298 buf[sizeof(buf) - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 26299 }
Marko Mikulicic 0:c0ecb8bf28eb 26300
Marko Mikulicic 0:c0ecb8bf28eb 26301 while (*p != '\0' && isspace(*(unsigned char *) p)) {
Marko Mikulicic 0:c0ecb8bf28eb 26302 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26303 }
Marko Mikulicic 0:c0ecb8bf28eb 26304
Marko Mikulicic 0:c0ecb8bf28eb 26305 result = cs_strtod(p, &end);
Marko Mikulicic 0:c0ecb8bf28eb 26306
Marko Mikulicic 0:c0ecb8bf28eb 26307 *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, result);
Marko Mikulicic 0:c0ecb8bf28eb 26308
Marko Mikulicic 0:c0ecb8bf28eb 26309 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26310 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26311 }
Marko Mikulicic 0:c0ecb8bf28eb 26312
Marko Mikulicic 0:c0ecb8bf28eb 26313 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26314 V7_PRIVATE enum v7_err Std_isNaN(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26315 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26316 v7_val_t arg0 = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26317 rcode = to_number_v(v7, v7_arg(v7, 0), &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 26318 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26319 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26320 }
Marko Mikulicic 0:c0ecb8bf28eb 26321
Marko Mikulicic 0:c0ecb8bf28eb 26322 *res = v7_mk_boolean(v7, isnan(v7_get_double(v7, arg0)));
Marko Mikulicic 0:c0ecb8bf28eb 26323
Marko Mikulicic 0:c0ecb8bf28eb 26324 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26325 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26326 }
Marko Mikulicic 0:c0ecb8bf28eb 26327
Marko Mikulicic 0:c0ecb8bf28eb 26328 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26329 V7_PRIVATE enum v7_err Std_isFinite(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26330 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26331 v7_val_t arg0 = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26332
Marko Mikulicic 0:c0ecb8bf28eb 26333 rcode = to_number_v(v7, v7_arg(v7, 0), &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 26334 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26335 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26336 }
Marko Mikulicic 0:c0ecb8bf28eb 26337
Marko Mikulicic 0:c0ecb8bf28eb 26338 *res = v7_mk_boolean(v7, is_finite(v7, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 26339
Marko Mikulicic 0:c0ecb8bf28eb 26340 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26341 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26342 }
Marko Mikulicic 0:c0ecb8bf28eb 26343
Marko Mikulicic 0:c0ecb8bf28eb 26344 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26345 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26346 V7_PRIVATE enum v7_err Std_exit(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26347 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26348 long exit_code;
Marko Mikulicic 0:c0ecb8bf28eb 26349
Marko Mikulicic 0:c0ecb8bf28eb 26350 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 26351
Marko Mikulicic 0:c0ecb8bf28eb 26352 rcode = to_long(v7, v7_arg(v7, 0), 0, &exit_code);
Marko Mikulicic 0:c0ecb8bf28eb 26353 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26354 /* `to_long` has thrown, so, will return 1 */
Marko Mikulicic 0:c0ecb8bf28eb 26355 exit_code = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26356 }
Marko Mikulicic 0:c0ecb8bf28eb 26357 exit(exit_code);
Marko Mikulicic 0:c0ecb8bf28eb 26358
Marko Mikulicic 0:c0ecb8bf28eb 26359 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26360 }
Marko Mikulicic 0:c0ecb8bf28eb 26361 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26362
Marko Mikulicic 0:c0ecb8bf28eb 26363 /*
Marko Mikulicic 0:c0ecb8bf28eb 26364 * Initialize standard library.
Marko Mikulicic 0:c0ecb8bf28eb 26365 *
Marko Mikulicic 0:c0ecb8bf28eb 26366 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 26367 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 26368 */
Marko Mikulicic 0:c0ecb8bf28eb 26369 /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 26370 v7_prop_attr_desc_t attr_internal =
Marko Mikulicic 0:c0ecb8bf28eb 26371 (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 26372
Marko Mikulicic 0:c0ecb8bf28eb 26373 /*
Marko Mikulicic 0:c0ecb8bf28eb 26374 * Ensure the first call to v7_mk_value will use a null proto:
Marko Mikulicic 0:c0ecb8bf28eb 26375 * {}.__proto__.__proto__ == null
Marko Mikulicic 0:c0ecb8bf28eb 26376 */
Marko Mikulicic 0:c0ecb8bf28eb 26377 v7->vals.object_prototype = mk_object(v7, V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26378 v7->vals.array_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26379 v7->vals.boolean_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26380 v7->vals.string_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26381 v7->vals.regexp_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26382 v7->vals.number_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26383 v7->vals.error_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26384 v7->vals.global_object = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26385 v7->vals.date_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26386 v7->vals.function_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26387 v7->vals.proxy_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26388
Marko Mikulicic 0:c0ecb8bf28eb 26389 set_method(v7, v7->vals.global_object, "eval", Std_eval, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26390 set_method(v7, v7->vals.global_object, "print", Std_print, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26391 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26392 set_method(v7, v7->vals.global_object, "exit", Std_exit, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26393 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26394 set_method(v7, v7->vals.global_object, "parseInt", Std_parseInt, 2);
Marko Mikulicic 0:c0ecb8bf28eb 26395 set_method(v7, v7->vals.global_object, "parseFloat", Std_parseFloat, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26396 set_method(v7, v7->vals.global_object, "isNaN", Std_isNaN, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26397 set_method(v7, v7->vals.global_object, "isFinite", Std_isFinite, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26398
Marko Mikulicic 0:c0ecb8bf28eb 26399 v7_def(v7, v7->vals.global_object, "Infinity", 8, attr_internal,
Marko Mikulicic 0:c0ecb8bf28eb 26400 v7_mk_number(v7, INFINITY));
Marko Mikulicic 0:c0ecb8bf28eb 26401 v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 26402
Marko Mikulicic 0:c0ecb8bf28eb 26403 init_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26404 init_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26405 init_error(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26406 init_boolean(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26407 #if V7_ENABLE__Math
Marko Mikulicic 0:c0ecb8bf28eb 26408 init_math(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26409 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26410 init_string(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26411 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 26412 init_regex(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26413 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26414 init_number(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26415 init_json(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26416 #if V7_ENABLE__Date
Marko Mikulicic 0:c0ecb8bf28eb 26417 init_date(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26418 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26419 init_function(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26420 init_js_stdlib(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26421
Marko Mikulicic 0:c0ecb8bf28eb 26422 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 26423 init_proxy(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26424 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26425 }
Marko Mikulicic 0:c0ecb8bf28eb 26426 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 26427 #line 1 "v7/src/js_stdlib.c"
Marko Mikulicic 0:c0ecb8bf28eb 26428 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26429 /*
Marko Mikulicic 0:c0ecb8bf28eb 26430 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 26431 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 26432 */
Marko Mikulicic 0:c0ecb8bf28eb 26433
Marko Mikulicic 0:c0ecb8bf28eb 26434 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 26435 /* because clang-format would break JS code, e.g. === converted to == = ... */
Marko Mikulicic 0:c0ecb8bf28eb 26436
Marko Mikulicic 0:c0ecb8bf28eb 26437 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26438 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26439 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26440 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26441
Marko Mikulicic 0:c0ecb8bf28eb 26442 #define STRINGIFY(x) #x
Marko Mikulicic 0:c0ecb8bf28eb 26443
Marko Mikulicic 0:c0ecb8bf28eb 26444 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 26445 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 26446 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 26447
Marko Mikulicic 0:c0ecb8bf28eb 26448 static const char js_array_indexOf[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26449 Object.defineProperty(Array.prototype, "indexOf", {
Marko Mikulicic 0:c0ecb8bf28eb 26450 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26451 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26452 value: function(a, x) {
Marko Mikulicic 0:c0ecb8bf28eb 26453 var i; var r = -1; var b = +x;
Marko Mikulicic 0:c0ecb8bf28eb 26454 if (!b || b < 0) b = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26455 for (i in this) if (i >= b && (r < 0 || i < r) && this[i] === a) r = +i;
Marko Mikulicic 0:c0ecb8bf28eb 26456 return r;
Marko Mikulicic 0:c0ecb8bf28eb 26457 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26458
Marko Mikulicic 0:c0ecb8bf28eb 26459 static const char js_array_lastIndexOf[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26460 Object.defineProperty(Array.prototype, "lastIndexOf", {
Marko Mikulicic 0:c0ecb8bf28eb 26461 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26462 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26463 value: function(a, x) {
Marko Mikulicic 0:c0ecb8bf28eb 26464 var i; var r = -1; var b = +x;
Marko Mikulicic 0:c0ecb8bf28eb 26465 if (isNaN(b) || b < 0 || b >= this.length) b = this.length - 1;
Marko Mikulicic 0:c0ecb8bf28eb 26466 for (i in this) if (i <= b && (r < 0 || i > r) && this[i] === a) r = +i;
Marko Mikulicic 0:c0ecb8bf28eb 26467 return r;
Marko Mikulicic 0:c0ecb8bf28eb 26468 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26469
Marko Mikulicic 0:c0ecb8bf28eb 26470 #if V7_ENABLE__Array__reduce
Marko Mikulicic 0:c0ecb8bf28eb 26471 static const char js_array_reduce[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26472 Object.defineProperty(Array.prototype, "reduce", {
Marko Mikulicic 0:c0ecb8bf28eb 26473 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26474 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26475 value: function(a, b) {
Marko Mikulicic 0:c0ecb8bf28eb 26476 var f = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26477 if (typeof(a) != "function") {
Marko Mikulicic 0:c0ecb8bf28eb 26478 throw new TypeError(a + " is not a function");
Marko Mikulicic 0:c0ecb8bf28eb 26479 }
Marko Mikulicic 0:c0ecb8bf28eb 26480 for (var k in this) {
Marko Mikulicic 0:c0ecb8bf28eb 26481 if (k > this.length) break;
Marko Mikulicic 0:c0ecb8bf28eb 26482 if (f == 0 && b === undefined) {
Marko Mikulicic 0:c0ecb8bf28eb 26483 b = this[k];
Marko Mikulicic 0:c0ecb8bf28eb 26484 f = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26485 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26486 b = a(b, this[k], k, this);
Marko Mikulicic 0:c0ecb8bf28eb 26487 }
Marko Mikulicic 0:c0ecb8bf28eb 26488 }
Marko Mikulicic 0:c0ecb8bf28eb 26489 return b;
Marko Mikulicic 0:c0ecb8bf28eb 26490 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26491 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26492
Marko Mikulicic 0:c0ecb8bf28eb 26493 static const char js_array_pop[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26494 Object.defineProperty(Array.prototype, "pop", {
Marko Mikulicic 0:c0ecb8bf28eb 26495 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26496 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26497 value: function() {
Marko Mikulicic 0:c0ecb8bf28eb 26498 var i = this.length - 1;
Marko Mikulicic 0:c0ecb8bf28eb 26499 return this.splice(i, 1)[0];
Marko Mikulicic 0:c0ecb8bf28eb 26500 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26501
Marko Mikulicic 0:c0ecb8bf28eb 26502 static const char js_array_shift[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26503 Object.defineProperty(Array.prototype, "shift", {
Marko Mikulicic 0:c0ecb8bf28eb 26504 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26505 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26506 value: function() {
Marko Mikulicic 0:c0ecb8bf28eb 26507 return this.splice(0, 1)[0];
Marko Mikulicic 0:c0ecb8bf28eb 26508 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26509
Marko Mikulicic 0:c0ecb8bf28eb 26510 #if V7_ENABLE__Function__call
Marko Mikulicic 0:c0ecb8bf28eb 26511 static const char js_function_call[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26512 Object.defineProperty(Function.prototype, "call", {
Marko Mikulicic 0:c0ecb8bf28eb 26513 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26514 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26515 value: function() {
Marko Mikulicic 0:c0ecb8bf28eb 26516 var t = arguments.splice(0, 1)[0];
Marko Mikulicic 0:c0ecb8bf28eb 26517 return this.apply(t, arguments);
Marko Mikulicic 0:c0ecb8bf28eb 26518 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26519 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26520
Marko Mikulicic 0:c0ecb8bf28eb 26521 #if V7_ENABLE__Function__bind
Marko Mikulicic 0:c0ecb8bf28eb 26522 static const char js_function_bind[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26523 Object.defineProperty(Function.prototype, "bind", {
Marko Mikulicic 0:c0ecb8bf28eb 26524 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26525 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26526 value: function(t) {
Marko Mikulicic 0:c0ecb8bf28eb 26527 var f = this;
Marko Mikulicic 0:c0ecb8bf28eb 26528 return function() {
Marko Mikulicic 0:c0ecb8bf28eb 26529 return f.apply(t, arguments);
Marko Mikulicic 0:c0ecb8bf28eb 26530 };
Marko Mikulicic 0:c0ecb8bf28eb 26531 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26532 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26533
Marko Mikulicic 0:c0ecb8bf28eb 26534 #if V7_ENABLE__Blob
Marko Mikulicic 0:c0ecb8bf28eb 26535 static const char js_Blob[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26536 function Blob(a) {
Marko Mikulicic 0:c0ecb8bf28eb 26537 this.a = a;
Marko Mikulicic 0:c0ecb8bf28eb 26538 });
Marko Mikulicic 0:c0ecb8bf28eb 26539 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26540
Marko Mikulicic 0:c0ecb8bf28eb 26541 static const char * const js_functions[] = {
Marko Mikulicic 0:c0ecb8bf28eb 26542 #if V7_ENABLE__Blob
Marko Mikulicic 0:c0ecb8bf28eb 26543 js_Blob,
Marko Mikulicic 0:c0ecb8bf28eb 26544 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26545 #if V7_ENABLE__Function__call
Marko Mikulicic 0:c0ecb8bf28eb 26546 js_function_call,
Marko Mikulicic 0:c0ecb8bf28eb 26547 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26548 #if V7_ENABLE__Function__bind
Marko Mikulicic 0:c0ecb8bf28eb 26549 js_function_bind,
Marko Mikulicic 0:c0ecb8bf28eb 26550 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26551 #if V7_ENABLE__Array__reduce
Marko Mikulicic 0:c0ecb8bf28eb 26552 js_array_reduce,
Marko Mikulicic 0:c0ecb8bf28eb 26553 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26554 js_array_indexOf,
Marko Mikulicic 0:c0ecb8bf28eb 26555 js_array_lastIndexOf,
Marko Mikulicic 0:c0ecb8bf28eb 26556 js_array_pop,
Marko Mikulicic 0:c0ecb8bf28eb 26557 js_array_shift
Marko Mikulicic 0:c0ecb8bf28eb 26558 };
Marko Mikulicic 0:c0ecb8bf28eb 26559
Marko Mikulicic 0:c0ecb8bf28eb 26560 V7_PRIVATE void init_js_stdlib(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 26561 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 26562 int i;
Marko Mikulicic 0:c0ecb8bf28eb 26563
Marko Mikulicic 0:c0ecb8bf28eb 26564 for(i = 0; i < (int) ARRAY_SIZE(js_functions); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 26565 if (v7_exec(v7, js_functions[i], &res) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26566 fprintf(stderr, "ex: %s:\n", js_functions[i]);
Marko Mikulicic 0:c0ecb8bf28eb 26567 v7_fprintln(stderr, v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 26568 }
Marko Mikulicic 0:c0ecb8bf28eb 26569 }
Marko Mikulicic 0:c0ecb8bf28eb 26570
Marko Mikulicic 0:c0ecb8bf28eb 26571 /* TODO(lsm): re-enable in a separate PR */
Marko Mikulicic 0:c0ecb8bf28eb 26572 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 26573 v7_exec(v7, &res, STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26574 Array.prototype.unshift = function() {
Marko Mikulicic 0:c0ecb8bf28eb 26575 var a = new Array(0, 0);
Marko Mikulicic 0:c0ecb8bf28eb 26576 Array.prototype.push.apply(a, arguments);
Marko Mikulicic 0:c0ecb8bf28eb 26577 Array.prototype.splice.apply(this, a);
Marko Mikulicic 0:c0ecb8bf28eb 26578 return this.length;
Marko Mikulicic 0:c0ecb8bf28eb 26579 };));
Marko Mikulicic 0:c0ecb8bf28eb 26580 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26581 }
Marko Mikulicic 0:c0ecb8bf28eb 26582
Marko Mikulicic 0:c0ecb8bf28eb 26583 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 26584 }
Marko Mikulicic 0:c0ecb8bf28eb 26585 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 26586 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 26587 #line 1 "v7/src/slre.c"
Marko Mikulicic 0:c0ecb8bf28eb 26588 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26589 /*
Marko Mikulicic 0:c0ecb8bf28eb 26590 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 26591 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 26592 *
Marko Mikulicic 0:c0ecb8bf28eb 26593 * This software is dual-licensed: you can redistribute it and/or modify
Marko Mikulicic 0:c0ecb8bf28eb 26594 * it under the terms of the GNU General Public License version 2 as
Marko Mikulicic 0:c0ecb8bf28eb 26595 * published by the Free Software Foundation. For the terms of this
Marko Mikulicic 0:c0ecb8bf28eb 26596 * license, see <http://www.gnu.org/licenses/>.
Marko Mikulicic 0:c0ecb8bf28eb 26597 *
Marko Mikulicic 0:c0ecb8bf28eb 26598 * You are free to use this software under the terms of the GNU General
Marko Mikulicic 0:c0ecb8bf28eb 26599 * Public License, but WITHOUT ANY WARRANTY; without even the implied
Marko Mikulicic 0:c0ecb8bf28eb 26600 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 26601 * See the GNU General Public License for more details.
Marko Mikulicic 0:c0ecb8bf28eb 26602 *
Marko Mikulicic 0:c0ecb8bf28eb 26603 * Alternatively, you can license this software under a commercial
Marko Mikulicic 0:c0ecb8bf28eb 26604 * license, as set out in <https://www.cesanta.com/license>.
Marko Mikulicic 0:c0ecb8bf28eb 26605 */
Marko Mikulicic 0:c0ecb8bf28eb 26606
Marko Mikulicic 0:c0ecb8bf28eb 26607 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26608
Marko Mikulicic 0:c0ecb8bf28eb 26609 #include <setjmp.h>
Marko Mikulicic 0:c0ecb8bf28eb 26610 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 26611 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 26612 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 26613
Marko Mikulicic 0:c0ecb8bf28eb 26614 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26615 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 26616 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26617
Marko Mikulicic 0:c0ecb8bf28eb 26618 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26619 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26620
Marko Mikulicic 0:c0ecb8bf28eb 26621 /* Limitations */
Marko Mikulicic 0:c0ecb8bf28eb 26622 #define SLRE_MAX_RANGES 32
Marko Mikulicic 0:c0ecb8bf28eb 26623 #define SLRE_MAX_SETS 16
Marko Mikulicic 0:c0ecb8bf28eb 26624 #define SLRE_MAX_REP 0xFFFF
Marko Mikulicic 0:c0ecb8bf28eb 26625
Marko Mikulicic 0:c0ecb8bf28eb 26626 #define SLRE_MALLOC malloc
Marko Mikulicic 0:c0ecb8bf28eb 26627 #define SLRE_FREE free
Marko Mikulicic 0:c0ecb8bf28eb 26628 #define SLRE_THROW(e, err_code) longjmp((e)->jmp_buf, (err_code))
Marko Mikulicic 0:c0ecb8bf28eb 26629
Marko Mikulicic 0:c0ecb8bf28eb 26630 static int hex(int c) {
Marko Mikulicic 0:c0ecb8bf28eb 26631 if (c >= '0' && c <= '9') return c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 26632 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
Marko Mikulicic 0:c0ecb8bf28eb 26633 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
Marko Mikulicic 0:c0ecb8bf28eb 26634 return -SLRE_INVALID_HEX_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26635 }
Marko Mikulicic 0:c0ecb8bf28eb 26636
Marko Mikulicic 0:c0ecb8bf28eb 26637 int nextesc(const char **p) {
Marko Mikulicic 0:c0ecb8bf28eb 26638 const unsigned char *s = (unsigned char *) (*p)++;
Marko Mikulicic 0:c0ecb8bf28eb 26639 switch (*s) {
Marko Mikulicic 0:c0ecb8bf28eb 26640 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 26641 return -SLRE_UNTERM_ESC_SEQ;
Marko Mikulicic 0:c0ecb8bf28eb 26642 case 'c':
Marko Mikulicic 0:c0ecb8bf28eb 26643 ++*p;
Marko Mikulicic 0:c0ecb8bf28eb 26644 return *s & 31;
Marko Mikulicic 0:c0ecb8bf28eb 26645 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 26646 return '\b';
Marko Mikulicic 0:c0ecb8bf28eb 26647 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 26648 return '\t';
Marko Mikulicic 0:c0ecb8bf28eb 26649 case 'n':
Marko Mikulicic 0:c0ecb8bf28eb 26650 return '\n';
Marko Mikulicic 0:c0ecb8bf28eb 26651 case 'v':
Marko Mikulicic 0:c0ecb8bf28eb 26652 return '\v';
Marko Mikulicic 0:c0ecb8bf28eb 26653 case 'f':
Marko Mikulicic 0:c0ecb8bf28eb 26654 return '\f';
Marko Mikulicic 0:c0ecb8bf28eb 26655 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 26656 return '\r';
Marko Mikulicic 0:c0ecb8bf28eb 26657 case '\\':
Marko Mikulicic 0:c0ecb8bf28eb 26658 return '\\';
Marko Mikulicic 0:c0ecb8bf28eb 26659 case 'u':
Marko Mikulicic 0:c0ecb8bf28eb 26660 if (isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) &&
Marko Mikulicic 0:c0ecb8bf28eb 26661 isxdigit(s[4])) {
Marko Mikulicic 0:c0ecb8bf28eb 26662 (*p) += 4;
Marko Mikulicic 0:c0ecb8bf28eb 26663 return hex(s[1]) << 12 | hex(s[2]) << 8 | hex(s[3]) << 4 | hex(s[4]);
Marko Mikulicic 0:c0ecb8bf28eb 26664 }
Marko Mikulicic 0:c0ecb8bf28eb 26665 return -SLRE_INVALID_HEX_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26666 case 'x':
Marko Mikulicic 0:c0ecb8bf28eb 26667 if (isxdigit(s[1]) && isxdigit(s[2])) {
Marko Mikulicic 0:c0ecb8bf28eb 26668 (*p) += 2;
Marko Mikulicic 0:c0ecb8bf28eb 26669 return (hex(s[1]) << 4) | hex(s[2]);
Marko Mikulicic 0:c0ecb8bf28eb 26670 }
Marko Mikulicic 0:c0ecb8bf28eb 26671 return -SLRE_INVALID_HEX_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26672 default:
Marko Mikulicic 0:c0ecb8bf28eb 26673 return -SLRE_INVALID_ESC_CHAR;
Marko Mikulicic 0:c0ecb8bf28eb 26674 }
Marko Mikulicic 0:c0ecb8bf28eb 26675 }
Marko Mikulicic 0:c0ecb8bf28eb 26676
Marko Mikulicic 0:c0ecb8bf28eb 26677 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 26678
Marko Mikulicic 0:c0ecb8bf28eb 26679 /* Parser Information */
Marko Mikulicic 0:c0ecb8bf28eb 26680 struct slre_node {
Marko Mikulicic 0:c0ecb8bf28eb 26681 unsigned char type;
Marko Mikulicic 0:c0ecb8bf28eb 26682 union {
Marko Mikulicic 0:c0ecb8bf28eb 26683 Rune c; /* character */
Marko Mikulicic 0:c0ecb8bf28eb 26684 struct slre_class *cp; /* class pointer */
Marko Mikulicic 0:c0ecb8bf28eb 26685 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26686 struct slre_node *x;
Marko Mikulicic 0:c0ecb8bf28eb 26687 union {
Marko Mikulicic 0:c0ecb8bf28eb 26688 struct slre_node *y;
Marko Mikulicic 0:c0ecb8bf28eb 26689 unsigned char n;
Marko Mikulicic 0:c0ecb8bf28eb 26690 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26691 unsigned char ng; /* not greedy flag */
Marko Mikulicic 0:c0ecb8bf28eb 26692 unsigned short min;
Marko Mikulicic 0:c0ecb8bf28eb 26693 unsigned short max;
Marko Mikulicic 0:c0ecb8bf28eb 26694 } rp;
Marko Mikulicic 0:c0ecb8bf28eb 26695 } y;
Marko Mikulicic 0:c0ecb8bf28eb 26696 } xy;
Marko Mikulicic 0:c0ecb8bf28eb 26697 } par;
Marko Mikulicic 0:c0ecb8bf28eb 26698 };
Marko Mikulicic 0:c0ecb8bf28eb 26699
Marko Mikulicic 0:c0ecb8bf28eb 26700 struct slre_range {
Marko Mikulicic 0:c0ecb8bf28eb 26701 unsigned short s, e;
Marko Mikulicic 0:c0ecb8bf28eb 26702 };
Marko Mikulicic 0:c0ecb8bf28eb 26703
Marko Mikulicic 0:c0ecb8bf28eb 26704 /* character class, each pair of rune's defines a range */
Marko Mikulicic 0:c0ecb8bf28eb 26705 struct slre_class {
Marko Mikulicic 0:c0ecb8bf28eb 26706 struct slre_range *end;
Marko Mikulicic 0:c0ecb8bf28eb 26707 struct slre_range spans[SLRE_MAX_RANGES];
Marko Mikulicic 0:c0ecb8bf28eb 26708 };
Marko Mikulicic 0:c0ecb8bf28eb 26709
Marko Mikulicic 0:c0ecb8bf28eb 26710 struct slre_instruction {
Marko Mikulicic 0:c0ecb8bf28eb 26711 unsigned char opcode;
Marko Mikulicic 0:c0ecb8bf28eb 26712 union {
Marko Mikulicic 0:c0ecb8bf28eb 26713 unsigned char n;
Marko Mikulicic 0:c0ecb8bf28eb 26714 Rune c; /* character */
Marko Mikulicic 0:c0ecb8bf28eb 26715 struct slre_class *cp; /* class pointer */
Marko Mikulicic 0:c0ecb8bf28eb 26716 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26717 struct slre_instruction *x;
Marko Mikulicic 0:c0ecb8bf28eb 26718 union {
Marko Mikulicic 0:c0ecb8bf28eb 26719 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26720 unsigned short min;
Marko Mikulicic 0:c0ecb8bf28eb 26721 unsigned short max;
Marko Mikulicic 0:c0ecb8bf28eb 26722 } rp;
Marko Mikulicic 0:c0ecb8bf28eb 26723 struct slre_instruction *y;
Marko Mikulicic 0:c0ecb8bf28eb 26724 } y;
Marko Mikulicic 0:c0ecb8bf28eb 26725 } xy;
Marko Mikulicic 0:c0ecb8bf28eb 26726 } par;
Marko Mikulicic 0:c0ecb8bf28eb 26727 };
Marko Mikulicic 0:c0ecb8bf28eb 26728
Marko Mikulicic 0:c0ecb8bf28eb 26729 struct slre_prog {
Marko Mikulicic 0:c0ecb8bf28eb 26730 struct slre_instruction *start, *end;
Marko Mikulicic 0:c0ecb8bf28eb 26731 unsigned int num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 26732 int flags;
Marko Mikulicic 0:c0ecb8bf28eb 26733 struct slre_class charset[SLRE_MAX_SETS];
Marko Mikulicic 0:c0ecb8bf28eb 26734 };
Marko Mikulicic 0:c0ecb8bf28eb 26735
Marko Mikulicic 0:c0ecb8bf28eb 26736 struct slre_env {
Marko Mikulicic 0:c0ecb8bf28eb 26737 int is_regex;
Marko Mikulicic 0:c0ecb8bf28eb 26738 const char *src;
Marko Mikulicic 0:c0ecb8bf28eb 26739 const char *src_end;
Marko Mikulicic 0:c0ecb8bf28eb 26740 Rune curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 26741
Marko Mikulicic 0:c0ecb8bf28eb 26742 struct slre_prog *prog;
Marko Mikulicic 0:c0ecb8bf28eb 26743 struct slre_node *pstart, *pend;
Marko Mikulicic 0:c0ecb8bf28eb 26744
Marko Mikulicic 0:c0ecb8bf28eb 26745 struct slre_node *caps[SLRE_MAX_CAPS];
Marko Mikulicic 0:c0ecb8bf28eb 26746 unsigned int num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 26747 unsigned int sets_num;
Marko Mikulicic 0:c0ecb8bf28eb 26748
Marko Mikulicic 0:c0ecb8bf28eb 26749 int lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 26750 struct slre_class *curr_set;
Marko Mikulicic 0:c0ecb8bf28eb 26751 int min_rep, max_rep;
Marko Mikulicic 0:c0ecb8bf28eb 26752
Marko Mikulicic 0:c0ecb8bf28eb 26753 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 26754 ::jmp_buf jmp_buf;
Marko Mikulicic 0:c0ecb8bf28eb 26755 #else
Marko Mikulicic 0:c0ecb8bf28eb 26756 jmp_buf jmp_buf;
Marko Mikulicic 0:c0ecb8bf28eb 26757 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26758 };
Marko Mikulicic 0:c0ecb8bf28eb 26759
Marko Mikulicic 0:c0ecb8bf28eb 26760 struct slre_thread {
Marko Mikulicic 0:c0ecb8bf28eb 26761 struct slre_thread *prev;
Marko Mikulicic 0:c0ecb8bf28eb 26762 struct slre_instruction *pc;
Marko Mikulicic 0:c0ecb8bf28eb 26763 const char *start;
Marko Mikulicic 0:c0ecb8bf28eb 26764 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 26765 };
Marko Mikulicic 0:c0ecb8bf28eb 26766
Marko Mikulicic 0:c0ecb8bf28eb 26767 enum slre_opcode {
Marko Mikulicic 0:c0ecb8bf28eb 26768 I_END = 10, /* Terminate: match found */
Marko Mikulicic 0:c0ecb8bf28eb 26769 I_ANY,
Marko Mikulicic 0:c0ecb8bf28eb 26770 P_ANY = I_ANY, /* Any character except newline, . */
Marko Mikulicic 0:c0ecb8bf28eb 26771 I_ANYNL, /* Any character including newline, . */
Marko Mikulicic 0:c0ecb8bf28eb 26772 I_BOL,
Marko Mikulicic 0:c0ecb8bf28eb 26773 P_BOL = I_BOL, /* Beginning of line, ^ */
Marko Mikulicic 0:c0ecb8bf28eb 26774 I_CH,
Marko Mikulicic 0:c0ecb8bf28eb 26775 P_CH = I_CH,
Marko Mikulicic 0:c0ecb8bf28eb 26776 I_EOL,
Marko Mikulicic 0:c0ecb8bf28eb 26777 P_EOL = I_EOL, /* End of line, $ */
Marko Mikulicic 0:c0ecb8bf28eb 26778 I_EOS,
Marko Mikulicic 0:c0ecb8bf28eb 26779 P_EOS = I_EOS, /* End of string, \0 */
Marko Mikulicic 0:c0ecb8bf28eb 26780 I_JUMP,
Marko Mikulicic 0:c0ecb8bf28eb 26781 I_LA,
Marko Mikulicic 0:c0ecb8bf28eb 26782 P_LA = I_LA,
Marko Mikulicic 0:c0ecb8bf28eb 26783 I_LA_N,
Marko Mikulicic 0:c0ecb8bf28eb 26784 P_LA_N = I_LA_N,
Marko Mikulicic 0:c0ecb8bf28eb 26785 I_LBRA,
Marko Mikulicic 0:c0ecb8bf28eb 26786 P_BRA = I_LBRA, /* Left bracket, ( */
Marko Mikulicic 0:c0ecb8bf28eb 26787 I_REF,
Marko Mikulicic 0:c0ecb8bf28eb 26788 P_REF = I_REF,
Marko Mikulicic 0:c0ecb8bf28eb 26789 I_REP,
Marko Mikulicic 0:c0ecb8bf28eb 26790 P_REP = I_REP,
Marko Mikulicic 0:c0ecb8bf28eb 26791 I_REP_INI,
Marko Mikulicic 0:c0ecb8bf28eb 26792 I_RBRA, /* Right bracket, ) */
Marko Mikulicic 0:c0ecb8bf28eb 26793 I_SET,
Marko Mikulicic 0:c0ecb8bf28eb 26794 P_SET = I_SET, /* Character set, [] */
Marko Mikulicic 0:c0ecb8bf28eb 26795 I_SET_N,
Marko Mikulicic 0:c0ecb8bf28eb 26796 P_SET_N = I_SET_N, /* Negated character set, [] */
Marko Mikulicic 0:c0ecb8bf28eb 26797 I_SPLIT,
Marko Mikulicic 0:c0ecb8bf28eb 26798 I_WORD,
Marko Mikulicic 0:c0ecb8bf28eb 26799 P_WORD = I_WORD,
Marko Mikulicic 0:c0ecb8bf28eb 26800 I_WORD_N,
Marko Mikulicic 0:c0ecb8bf28eb 26801 P_WORD_N = I_WORD_N,
Marko Mikulicic 0:c0ecb8bf28eb 26802 P_ALT, /* Alternation, | */
Marko Mikulicic 0:c0ecb8bf28eb 26803 P_CAT, /* Concatentation, implicit operator */
Marko Mikulicic 0:c0ecb8bf28eb 26804 L_CH = 256,
Marko Mikulicic 0:c0ecb8bf28eb 26805 L_COUNT, /* {M,N} */
Marko Mikulicic 0:c0ecb8bf28eb 26806 L_EOS, /* End of string, \0 */
Marko Mikulicic 0:c0ecb8bf28eb 26807 L_LA, /* "(?=" lookahead */
Marko Mikulicic 0:c0ecb8bf28eb 26808 L_LA_CAP, /* "(?:" lookahead, capture */
Marko Mikulicic 0:c0ecb8bf28eb 26809 L_LA_N, /* "(?!" negative lookahead */
Marko Mikulicic 0:c0ecb8bf28eb 26810 L_REF, /* "\1" back-reference */
Marko Mikulicic 0:c0ecb8bf28eb 26811 L_CHSET, /* character set */
Marko Mikulicic 0:c0ecb8bf28eb 26812 L_SET_N, /* negative character set */
Marko Mikulicic 0:c0ecb8bf28eb 26813 L_WORD, /* "\b" word boundary */
Marko Mikulicic 0:c0ecb8bf28eb 26814 L_WORD_N /* "\B" non-word boundary */
Marko Mikulicic 0:c0ecb8bf28eb 26815 };
Marko Mikulicic 0:c0ecb8bf28eb 26816
Marko Mikulicic 0:c0ecb8bf28eb 26817 static signed char dec(int c) {
Marko Mikulicic 0:c0ecb8bf28eb 26818 if (isdigitrune(c)) return c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 26819 return SLRE_INVALID_DEC_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26820 }
Marko Mikulicic 0:c0ecb8bf28eb 26821
Marko Mikulicic 0:c0ecb8bf28eb 26822 static unsigned char re_dec_digit(struct slre_env *e, int c) {
Marko Mikulicic 0:c0ecb8bf28eb 26823 signed char ret = dec(c);
Marko Mikulicic 0:c0ecb8bf28eb 26824 if (ret < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 26825 SLRE_THROW(e, SLRE_INVALID_DEC_DIGIT);
Marko Mikulicic 0:c0ecb8bf28eb 26826 }
Marko Mikulicic 0:c0ecb8bf28eb 26827 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 26828 }
Marko Mikulicic 0:c0ecb8bf28eb 26829
Marko Mikulicic 0:c0ecb8bf28eb 26830 static int re_nextc(Rune *r, const char **src, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 26831 *r = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26832 if (*src >= src_end) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26833 *src += chartorune(r, *src);
Marko Mikulicic 0:c0ecb8bf28eb 26834 if (*r == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 26835 const char *tmp_s = *src;
Marko Mikulicic 0:c0ecb8bf28eb 26836 int i = nextesc(src);
Marko Mikulicic 0:c0ecb8bf28eb 26837 switch (i) {
Marko Mikulicic 0:c0ecb8bf28eb 26838 case -SLRE_INVALID_ESC_CHAR:
Marko Mikulicic 0:c0ecb8bf28eb 26839 *r = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 26840 *src = tmp_s;
Marko Mikulicic 0:c0ecb8bf28eb 26841 *src += chartorune(r, *src);
Marko Mikulicic 0:c0ecb8bf28eb 26842 break;
Marko Mikulicic 0:c0ecb8bf28eb 26843 case -SLRE_INVALID_HEX_DIGIT:
Marko Mikulicic 0:c0ecb8bf28eb 26844 default:
Marko Mikulicic 0:c0ecb8bf28eb 26845 *r = i;
Marko Mikulicic 0:c0ecb8bf28eb 26846 }
Marko Mikulicic 0:c0ecb8bf28eb 26847 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 26848 }
Marko Mikulicic 0:c0ecb8bf28eb 26849 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26850 }
Marko Mikulicic 0:c0ecb8bf28eb 26851
Marko Mikulicic 0:c0ecb8bf28eb 26852 static int re_nextc_raw(Rune *r, const char **src, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 26853 *r = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26854 if (*src >= src_end) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26855 *src += chartorune(r, *src);
Marko Mikulicic 0:c0ecb8bf28eb 26856 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26857 }
Marko Mikulicic 0:c0ecb8bf28eb 26858
Marko Mikulicic 0:c0ecb8bf28eb 26859 static int re_nextc_env(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26860 return re_nextc(&e->curr_rune, &e->src, e->src_end);
Marko Mikulicic 0:c0ecb8bf28eb 26861 }
Marko Mikulicic 0:c0ecb8bf28eb 26862
Marko Mikulicic 0:c0ecb8bf28eb 26863 static void re_nchset(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26864 if (e->sets_num >= nelem(e->prog->charset)) {
Marko Mikulicic 0:c0ecb8bf28eb 26865 SLRE_THROW(e, SLRE_TOO_MANY_CHARSETS);
Marko Mikulicic 0:c0ecb8bf28eb 26866 }
Marko Mikulicic 0:c0ecb8bf28eb 26867 e->curr_set = e->prog->charset + e->sets_num++;
Marko Mikulicic 0:c0ecb8bf28eb 26868 e->curr_set->end = e->curr_set->spans;
Marko Mikulicic 0:c0ecb8bf28eb 26869 }
Marko Mikulicic 0:c0ecb8bf28eb 26870
Marko Mikulicic 0:c0ecb8bf28eb 26871 static void re_rng2set(struct slre_env *e, Rune start, Rune end) {
Marko Mikulicic 0:c0ecb8bf28eb 26872 if (start > end) {
Marko Mikulicic 0:c0ecb8bf28eb 26873 SLRE_THROW(e, SLRE_INV_CHARSET_RANGE);
Marko Mikulicic 0:c0ecb8bf28eb 26874 }
Marko Mikulicic 0:c0ecb8bf28eb 26875 if (e->curr_set->end + 2 == e->curr_set->spans + nelem(e->curr_set->spans)) {
Marko Mikulicic 0:c0ecb8bf28eb 26876 SLRE_THROW(e, SLRE_CHARSET_TOO_LARGE);
Marko Mikulicic 0:c0ecb8bf28eb 26877 }
Marko Mikulicic 0:c0ecb8bf28eb 26878 e->curr_set->end->s = start;
Marko Mikulicic 0:c0ecb8bf28eb 26879 e->curr_set->end->e = end;
Marko Mikulicic 0:c0ecb8bf28eb 26880 e->curr_set->end++;
Marko Mikulicic 0:c0ecb8bf28eb 26881 }
Marko Mikulicic 0:c0ecb8bf28eb 26882
Marko Mikulicic 0:c0ecb8bf28eb 26883 #define re_char2set(e, c) re_rng2set(e, c, c)
Marko Mikulicic 0:c0ecb8bf28eb 26884
Marko Mikulicic 0:c0ecb8bf28eb 26885 #define re_d_2set(e) re_rng2set(e, '0', '9')
Marko Mikulicic 0:c0ecb8bf28eb 26886
Marko Mikulicic 0:c0ecb8bf28eb 26887 static void re_D_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26888 re_rng2set(e, 0, '0' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26889 re_rng2set(e, '9' + 1, 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 26890 }
Marko Mikulicic 0:c0ecb8bf28eb 26891
Marko Mikulicic 0:c0ecb8bf28eb 26892 static void re_s_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26893 re_char2set(e, 0x9);
Marko Mikulicic 0:c0ecb8bf28eb 26894 re_rng2set(e, 0xA, 0xD);
Marko Mikulicic 0:c0ecb8bf28eb 26895 re_char2set(e, 0x20);
Marko Mikulicic 0:c0ecb8bf28eb 26896 re_char2set(e, 0xA0);
Marko Mikulicic 0:c0ecb8bf28eb 26897 re_rng2set(e, 0x2028, 0x2029);
Marko Mikulicic 0:c0ecb8bf28eb 26898 re_char2set(e, 0xFEFF);
Marko Mikulicic 0:c0ecb8bf28eb 26899 }
Marko Mikulicic 0:c0ecb8bf28eb 26900
Marko Mikulicic 0:c0ecb8bf28eb 26901 static void re_S_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26902 re_rng2set(e, 0, 0x9 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26903 re_rng2set(e, 0xD + 1, 0x20 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26904 re_rng2set(e, 0x20 + 1, 0xA0 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26905 re_rng2set(e, 0xA0 + 1, 0x2028 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26906 re_rng2set(e, 0x2029 + 1, 0xFEFF - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26907 re_rng2set(e, 0xFEFF + 1, 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 26908 }
Marko Mikulicic 0:c0ecb8bf28eb 26909
Marko Mikulicic 0:c0ecb8bf28eb 26910 static void re_w_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26911 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26912 re_rng2set(e, 'A', 'Z');
Marko Mikulicic 0:c0ecb8bf28eb 26913 re_char2set(e, '_');
Marko Mikulicic 0:c0ecb8bf28eb 26914 re_rng2set(e, 'a', 'z');
Marko Mikulicic 0:c0ecb8bf28eb 26915 }
Marko Mikulicic 0:c0ecb8bf28eb 26916
Marko Mikulicic 0:c0ecb8bf28eb 26917 static void re_W_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26918 re_rng2set(e, 0, '0' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26919 re_rng2set(e, '9' + 1, 'A' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26920 re_rng2set(e, 'Z' + 1, '_' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26921 re_rng2set(e, '_' + 1, 'a' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26922 re_rng2set(e, 'z' + 1, 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 26923 }
Marko Mikulicic 0:c0ecb8bf28eb 26924
Marko Mikulicic 0:c0ecb8bf28eb 26925 static unsigned char re_endofcount(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 26926 switch (c) {
Marko Mikulicic 0:c0ecb8bf28eb 26927 case ',':
Marko Mikulicic 0:c0ecb8bf28eb 26928 case '}':
Marko Mikulicic 0:c0ecb8bf28eb 26929 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 26930 }
Marko Mikulicic 0:c0ecb8bf28eb 26931 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26932 }
Marko Mikulicic 0:c0ecb8bf28eb 26933
Marko Mikulicic 0:c0ecb8bf28eb 26934 static void re_ex_num_overfl(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26935 SLRE_THROW(e, SLRE_NUM_OVERFLOW);
Marko Mikulicic 0:c0ecb8bf28eb 26936 }
Marko Mikulicic 0:c0ecb8bf28eb 26937
Marko Mikulicic 0:c0ecb8bf28eb 26938 static enum slre_opcode re_countrep(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26939 e->min_rep = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26940 while (e->src < e->src_end && !re_endofcount(e->curr_rune = *e->src++)) {
Marko Mikulicic 0:c0ecb8bf28eb 26941 e->min_rep = e->min_rep * 10 + re_dec_digit(e, e->curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 26942 if (e->min_rep >= SLRE_MAX_REP) re_ex_num_overfl(e);
Marko Mikulicic 0:c0ecb8bf28eb 26943 }
Marko Mikulicic 0:c0ecb8bf28eb 26944
Marko Mikulicic 0:c0ecb8bf28eb 26945 if (e->curr_rune != ',') {
Marko Mikulicic 0:c0ecb8bf28eb 26946 e->max_rep = e->min_rep;
Marko Mikulicic 0:c0ecb8bf28eb 26947 return L_COUNT;
Marko Mikulicic 0:c0ecb8bf28eb 26948 }
Marko Mikulicic 0:c0ecb8bf28eb 26949 e->max_rep = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26950 while (e->src < e->src_end && (e->curr_rune = *e->src++) != '}') {
Marko Mikulicic 0:c0ecb8bf28eb 26951 e->max_rep = e->max_rep * 10 + re_dec_digit(e, e->curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 26952 if (e->max_rep >= SLRE_MAX_REP) re_ex_num_overfl(e);
Marko Mikulicic 0:c0ecb8bf28eb 26953 }
Marko Mikulicic 0:c0ecb8bf28eb 26954 if (!e->max_rep) {
Marko Mikulicic 0:c0ecb8bf28eb 26955 e->max_rep = SLRE_MAX_REP;
Marko Mikulicic 0:c0ecb8bf28eb 26956 return L_COUNT;
Marko Mikulicic 0:c0ecb8bf28eb 26957 }
Marko Mikulicic 0:c0ecb8bf28eb 26958
Marko Mikulicic 0:c0ecb8bf28eb 26959 return L_COUNT;
Marko Mikulicic 0:c0ecb8bf28eb 26960 }
Marko Mikulicic 0:c0ecb8bf28eb 26961
Marko Mikulicic 0:c0ecb8bf28eb 26962 static enum slre_opcode re_lexset(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26963 Rune ch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26964 unsigned char esc, ch_fl = 0, dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26965 enum slre_opcode type = L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 26966
Marko Mikulicic 0:c0ecb8bf28eb 26967 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 26968
Marko Mikulicic 0:c0ecb8bf28eb 26969 esc = re_nextc_env(e);
Marko Mikulicic 0:c0ecb8bf28eb 26970 if (!esc && e->curr_rune == '^') {
Marko Mikulicic 0:c0ecb8bf28eb 26971 type = L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 26972 esc = re_nextc_env(e);
Marko Mikulicic 0:c0ecb8bf28eb 26973 }
Marko Mikulicic 0:c0ecb8bf28eb 26974
Marko Mikulicic 0:c0ecb8bf28eb 26975 for (; esc || e->curr_rune != ']'; esc = re_nextc_env(e)) {
Marko Mikulicic 0:c0ecb8bf28eb 26976 if (!e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 26977 SLRE_THROW(e, SLRE_MALFORMED_CHARSET);
Marko Mikulicic 0:c0ecb8bf28eb 26978 }
Marko Mikulicic 0:c0ecb8bf28eb 26979 if (esc) {
Marko Mikulicic 0:c0ecb8bf28eb 26980 if (strchr("DdSsWw", e->curr_rune)) {
Marko Mikulicic 0:c0ecb8bf28eb 26981 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 26982 re_char2set(e, ch);
Marko Mikulicic 0:c0ecb8bf28eb 26983 if (dash_fl) re_char2set(e, '-');
Marko Mikulicic 0:c0ecb8bf28eb 26984 }
Marko Mikulicic 0:c0ecb8bf28eb 26985 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 26986 case 'D':
Marko Mikulicic 0:c0ecb8bf28eb 26987 re_D_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26988 break;
Marko Mikulicic 0:c0ecb8bf28eb 26989 case 'd':
Marko Mikulicic 0:c0ecb8bf28eb 26990 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26991 break;
Marko Mikulicic 0:c0ecb8bf28eb 26992 case 'S':
Marko Mikulicic 0:c0ecb8bf28eb 26993 re_S_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26994 break;
Marko Mikulicic 0:c0ecb8bf28eb 26995 case 's':
Marko Mikulicic 0:c0ecb8bf28eb 26996 re_s_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26997 break;
Marko Mikulicic 0:c0ecb8bf28eb 26998 case 'W':
Marko Mikulicic 0:c0ecb8bf28eb 26999 re_W_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27000 break;
Marko Mikulicic 0:c0ecb8bf28eb 27001 case 'w':
Marko Mikulicic 0:c0ecb8bf28eb 27002 re_w_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27003 break;
Marko Mikulicic 0:c0ecb8bf28eb 27004 }
Marko Mikulicic 0:c0ecb8bf28eb 27005 ch_fl = dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27006 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27007 }
Marko Mikulicic 0:c0ecb8bf28eb 27008 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 27009 default:
Marko Mikulicic 0:c0ecb8bf28eb 27010 /* case '-':
Marko Mikulicic 0:c0ecb8bf28eb 27011 case '\\':
Marko Mikulicic 0:c0ecb8bf28eb 27012 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 27013 case '/':
Marko Mikulicic 0:c0ecb8bf28eb 27014 case ']':
Marko Mikulicic 0:c0ecb8bf28eb 27015 case '|': */
Marko Mikulicic 0:c0ecb8bf28eb 27016 break;
Marko Mikulicic 0:c0ecb8bf28eb 27017 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 27018 e->curr_rune = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27019 break;
Marko Mikulicic 0:c0ecb8bf28eb 27020 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 27021 e->curr_rune = '\b';
Marko Mikulicic 0:c0ecb8bf28eb 27022 break;
Marko Mikulicic 0:c0ecb8bf28eb 27023 /* default:
Marko Mikulicic 0:c0ecb8bf28eb 27024 SLRE_THROW(e->catch_point, e->err_msg,
Marko Mikulicic 0:c0ecb8bf28eb 27025 SLRE_INVALID_ESC_CHAR); */
Marko Mikulicic 0:c0ecb8bf28eb 27026 }
Marko Mikulicic 0:c0ecb8bf28eb 27027 } else {
Marko Mikulicic 0:c0ecb8bf28eb 27028 if (e->curr_rune == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 27029 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 27030 if (dash_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 27031 re_rng2set(e, ch, '-');
Marko Mikulicic 0:c0ecb8bf28eb 27032 ch_fl = dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27033 } else
Marko Mikulicic 0:c0ecb8bf28eb 27034 dash_fl = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27035 } else {
Marko Mikulicic 0:c0ecb8bf28eb 27036 ch = '-';
Marko Mikulicic 0:c0ecb8bf28eb 27037 ch_fl = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27038 }
Marko Mikulicic 0:c0ecb8bf28eb 27039 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27040 }
Marko Mikulicic 0:c0ecb8bf28eb 27041 }
Marko Mikulicic 0:c0ecb8bf28eb 27042 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 27043 if (dash_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 27044 re_rng2set(e, ch, e->curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 27045 ch_fl = dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27046 } else {
Marko Mikulicic 0:c0ecb8bf28eb 27047 re_char2set(e, ch);
Marko Mikulicic 0:c0ecb8bf28eb 27048 ch = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27049 }
Marko Mikulicic 0:c0ecb8bf28eb 27050 } else {
Marko Mikulicic 0:c0ecb8bf28eb 27051 ch = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27052 ch_fl = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27053 }
Marko Mikulicic 0:c0ecb8bf28eb 27054 }
Marko Mikulicic 0:c0ecb8bf28eb 27055 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 27056 re_char2set(e, ch);
Marko Mikulicic 0:c0ecb8bf28eb 27057 if (dash_fl) re_char2set(e, '-');
Marko Mikulicic 0:c0ecb8bf28eb 27058 }
Marko Mikulicic 0:c0ecb8bf28eb 27059 return type;
Marko Mikulicic 0:c0ecb8bf28eb 27060 }
Marko Mikulicic 0:c0ecb8bf28eb 27061
Marko Mikulicic 0:c0ecb8bf28eb 27062 static int re_lexer(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 27063 if (re_nextc_env(e)) {
Marko Mikulicic 0:c0ecb8bf28eb 27064 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 27065 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 27066 e->curr_rune = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27067 return L_EOS;
Marko Mikulicic 0:c0ecb8bf28eb 27068 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 27069 return L_WORD;
Marko Mikulicic 0:c0ecb8bf28eb 27070 case 'B':
Marko Mikulicic 0:c0ecb8bf28eb 27071 return L_WORD_N;
Marko Mikulicic 0:c0ecb8bf28eb 27072 case 'd':
Marko Mikulicic 0:c0ecb8bf28eb 27073 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27074 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27075 return L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 27076 case 'D':
Marko Mikulicic 0:c0ecb8bf28eb 27077 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27078 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27079 return L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 27080 case 's':
Marko Mikulicic 0:c0ecb8bf28eb 27081 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27082 re_s_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27083 return L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 27084 case 'S':
Marko Mikulicic 0:c0ecb8bf28eb 27085 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27086 re_s_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27087 return L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 27088 case 'w':
Marko Mikulicic 0:c0ecb8bf28eb 27089 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27090 re_w_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27091 return L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 27092 case 'W':
Marko Mikulicic 0:c0ecb8bf28eb 27093 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27094 re_w_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27095 return L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 27096 }
Marko Mikulicic 0:c0ecb8bf28eb 27097 if (isdigitrune(e->curr_rune)) {
Marko Mikulicic 0:c0ecb8bf28eb 27098 e->curr_rune -= '0';
Marko Mikulicic 0:c0ecb8bf28eb 27099 if (isdigitrune(*e->src))
Marko Mikulicic 0:c0ecb8bf28eb 27100 e->curr_rune = e->curr_rune * 10 + *e->src++ - '0';
Marko Mikulicic 0:c0ecb8bf28eb 27101 return L_REF;
Marko Mikulicic 0:c0ecb8bf28eb 27102 }
Marko Mikulicic 0:c0ecb8bf28eb 27103 return L_CH;
Marko Mikulicic 0:c0ecb8bf28eb 27104 }
Marko Mikulicic 0:c0ecb8bf28eb 27105
Marko Mikulicic 0:c0ecb8bf28eb 27106 if (e->is_regex) {
Marko Mikulicic 0:c0ecb8bf28eb 27107 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 27108 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27109 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27110 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 27111 case ')':
Marko Mikulicic 0:c0ecb8bf28eb 27112 case '*':
Marko Mikulicic 0:c0ecb8bf28eb 27113 case '+':
Marko Mikulicic 0:c0ecb8bf28eb 27114 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 27115 case '?':
Marko Mikulicic 0:c0ecb8bf28eb 27116 case '^':
Marko Mikulicic 0:c0ecb8bf28eb 27117 case '|':
Marko Mikulicic 0:c0ecb8bf28eb 27118 return e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27119 case '{':
Marko Mikulicic 0:c0ecb8bf28eb 27120 return re_countrep(e);
Marko Mikulicic 0:c0ecb8bf28eb 27121 case '[':
Marko Mikulicic 0:c0ecb8bf28eb 27122 return re_lexset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27123 case '(':
Marko Mikulicic 0:c0ecb8bf28eb 27124 if (e->src[0] == '?') switch (e->src[1]) {
Marko Mikulicic 0:c0ecb8bf28eb 27125 case '=':
Marko Mikulicic 0:c0ecb8bf28eb 27126 e->src += 2;
Marko Mikulicic 0:c0ecb8bf28eb 27127 return L_LA;
Marko Mikulicic 0:c0ecb8bf28eb 27128 case ':':
Marko Mikulicic 0:c0ecb8bf28eb 27129 e->src += 2;
Marko Mikulicic 0:c0ecb8bf28eb 27130 return L_LA_CAP;
Marko Mikulicic 0:c0ecb8bf28eb 27131 case '!':
Marko Mikulicic 0:c0ecb8bf28eb 27132 e->src += 2;
Marko Mikulicic 0:c0ecb8bf28eb 27133 return L_LA_N;
Marko Mikulicic 0:c0ecb8bf28eb 27134 }
Marko Mikulicic 0:c0ecb8bf28eb 27135 return '(';
Marko Mikulicic 0:c0ecb8bf28eb 27136 }
Marko Mikulicic 0:c0ecb8bf28eb 27137 } else if (e->curr_rune == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 27138 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27139 }
Marko Mikulicic 0:c0ecb8bf28eb 27140
Marko Mikulicic 0:c0ecb8bf28eb 27141 return L_CH;
Marko Mikulicic 0:c0ecb8bf28eb 27142 }
Marko Mikulicic 0:c0ecb8bf28eb 27143
Marko Mikulicic 0:c0ecb8bf28eb 27144 #define RE_NEXT(env) (env)->lookahead = re_lexer(env)
Marko Mikulicic 0:c0ecb8bf28eb 27145 #define RE_ACCEPT(env, t) ((env)->lookahead == (t) ? RE_NEXT(env), 1 : 0)
Marko Mikulicic 0:c0ecb8bf28eb 27146
Marko Mikulicic 0:c0ecb8bf28eb 27147 static struct slre_node *re_nnode(struct slre_env *e, int type) {
Marko Mikulicic 0:c0ecb8bf28eb 27148 memset(e->pend, 0, sizeof(struct slre_node));
Marko Mikulicic 0:c0ecb8bf28eb 27149 e->pend->type = type;
Marko Mikulicic 0:c0ecb8bf28eb 27150 return e->pend++;
Marko Mikulicic 0:c0ecb8bf28eb 27151 }
Marko Mikulicic 0:c0ecb8bf28eb 27152
Marko Mikulicic 0:c0ecb8bf28eb 27153 static unsigned char re_isemptynd(struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27154 if (!nd) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27155 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27156 default:
Marko Mikulicic 0:c0ecb8bf28eb 27157 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27158 case P_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27159 case P_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27160 case P_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27161 case P_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27162 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27163 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27164 case P_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27165 return re_isemptynd(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27166 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27167 return re_isemptynd(nd->par.xy.x) && re_isemptynd(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27168 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27169 return re_isemptynd(nd->par.xy.x) || re_isemptynd(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27170 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27171 return re_isemptynd(nd->par.xy.x) || !nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27172 }
Marko Mikulicic 0:c0ecb8bf28eb 27173 }
Marko Mikulicic 0:c0ecb8bf28eb 27174
Marko Mikulicic 0:c0ecb8bf28eb 27175 static struct slre_node *re_nrep(struct slre_env *e, struct slre_node *nd,
Marko Mikulicic 0:c0ecb8bf28eb 27176 int ng, unsigned short min,
Marko Mikulicic 0:c0ecb8bf28eb 27177 unsigned short max) {
Marko Mikulicic 0:c0ecb8bf28eb 27178 struct slre_node *rep = re_nnode(e, P_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27179 if (max == SLRE_MAX_REP && re_isemptynd(nd)) {
Marko Mikulicic 0:c0ecb8bf28eb 27180 SLRE_THROW(e, SLRE_INF_LOOP_M_EMP_STR);
Marko Mikulicic 0:c0ecb8bf28eb 27181 }
Marko Mikulicic 0:c0ecb8bf28eb 27182 rep->par.xy.y.rp.ng = ng;
Marko Mikulicic 0:c0ecb8bf28eb 27183 rep->par.xy.y.rp.min = min;
Marko Mikulicic 0:c0ecb8bf28eb 27184 rep->par.xy.y.rp.max = max;
Marko Mikulicic 0:c0ecb8bf28eb 27185 rep->par.xy.x = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27186 return rep;
Marko Mikulicic 0:c0ecb8bf28eb 27187 }
Marko Mikulicic 0:c0ecb8bf28eb 27188
Marko Mikulicic 0:c0ecb8bf28eb 27189 static struct slre_node *re_parser(struct slre_env *e);
Marko Mikulicic 0:c0ecb8bf28eb 27190
Marko Mikulicic 0:c0ecb8bf28eb 27191 static struct slre_node *re_parse_la(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 27192 struct slre_node *nd;
Marko Mikulicic 0:c0ecb8bf28eb 27193 int min, max;
Marko Mikulicic 0:c0ecb8bf28eb 27194 switch (e->lookahead) {
Marko Mikulicic 0:c0ecb8bf28eb 27195 case '^':
Marko Mikulicic 0:c0ecb8bf28eb 27196 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27197 return re_nnode(e, P_BOL);
Marko Mikulicic 0:c0ecb8bf28eb 27198 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 27199 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27200 return re_nnode(e, P_EOL);
Marko Mikulicic 0:c0ecb8bf28eb 27201 case L_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27202 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27203 return re_nnode(e, P_EOS);
Marko Mikulicic 0:c0ecb8bf28eb 27204 case L_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27205 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27206 return re_nnode(e, P_WORD);
Marko Mikulicic 0:c0ecb8bf28eb 27207 case L_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27208 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27209 return re_nnode(e, P_WORD_N);
Marko Mikulicic 0:c0ecb8bf28eb 27210 }
Marko Mikulicic 0:c0ecb8bf28eb 27211
Marko Mikulicic 0:c0ecb8bf28eb 27212 switch (e->lookahead) {
Marko Mikulicic 0:c0ecb8bf28eb 27213 case L_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27214 nd = re_nnode(e, P_CH);
Marko Mikulicic 0:c0ecb8bf28eb 27215 nd->par.c = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27216 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27217 break;
Marko Mikulicic 0:c0ecb8bf28eb 27218 case L_CHSET:
Marko Mikulicic 0:c0ecb8bf28eb 27219 nd = re_nnode(e, P_SET);
Marko Mikulicic 0:c0ecb8bf28eb 27220 nd->par.cp = e->curr_set;
Marko Mikulicic 0:c0ecb8bf28eb 27221 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27222 break;
Marko Mikulicic 0:c0ecb8bf28eb 27223 case L_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27224 nd = re_nnode(e, P_SET_N);
Marko Mikulicic 0:c0ecb8bf28eb 27225 nd->par.cp = e->curr_set;
Marko Mikulicic 0:c0ecb8bf28eb 27226 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27227 break;
Marko Mikulicic 0:c0ecb8bf28eb 27228 case L_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27229 nd = re_nnode(e, P_REF);
Marko Mikulicic 0:c0ecb8bf28eb 27230 if (!e->curr_rune || e->curr_rune > e->num_captures ||
Marko Mikulicic 0:c0ecb8bf28eb 27231 !e->caps[e->curr_rune]) {
Marko Mikulicic 0:c0ecb8bf28eb 27232 SLRE_THROW(e, SLRE_INVALID_BACK_REFERENCE);
Marko Mikulicic 0:c0ecb8bf28eb 27233 }
Marko Mikulicic 0:c0ecb8bf28eb 27234 nd->par.xy.y.n = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27235 nd->par.xy.x = e->caps[e->curr_rune];
Marko Mikulicic 0:c0ecb8bf28eb 27236 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27237 break;
Marko Mikulicic 0:c0ecb8bf28eb 27238 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 27239 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27240 nd = re_nnode(e, P_ANY);
Marko Mikulicic 0:c0ecb8bf28eb 27241 break;
Marko Mikulicic 0:c0ecb8bf28eb 27242 case '(':
Marko Mikulicic 0:c0ecb8bf28eb 27243 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27244 nd = re_nnode(e, P_BRA);
Marko Mikulicic 0:c0ecb8bf28eb 27245 if (e->num_captures == SLRE_MAX_CAPS) {
Marko Mikulicic 0:c0ecb8bf28eb 27246 SLRE_THROW(e, SLRE_TOO_MANY_CAPTURES);
Marko Mikulicic 0:c0ecb8bf28eb 27247 }
Marko Mikulicic 0:c0ecb8bf28eb 27248 nd->par.xy.y.n = e->num_captures++;
Marko Mikulicic 0:c0ecb8bf28eb 27249 nd->par.xy.x = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27250 e->caps[nd->par.xy.y.n] = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27251 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27252 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27253 }
Marko Mikulicic 0:c0ecb8bf28eb 27254 break;
Marko Mikulicic 0:c0ecb8bf28eb 27255 case L_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27256 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27257 nd = re_nnode(e, P_LA);
Marko Mikulicic 0:c0ecb8bf28eb 27258 nd->par.xy.x = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27259 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27260 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27261 }
Marko Mikulicic 0:c0ecb8bf28eb 27262 break;
Marko Mikulicic 0:c0ecb8bf28eb 27263 case L_LA_CAP:
Marko Mikulicic 0:c0ecb8bf28eb 27264 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27265 nd = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27266 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27267 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27268 }
Marko Mikulicic 0:c0ecb8bf28eb 27269 break;
Marko Mikulicic 0:c0ecb8bf28eb 27270 case L_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27271 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27272 nd = re_nnode(e, P_LA_N);
Marko Mikulicic 0:c0ecb8bf28eb 27273 nd->par.xy.x = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27274 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27275 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27276 }
Marko Mikulicic 0:c0ecb8bf28eb 27277 break;
Marko Mikulicic 0:c0ecb8bf28eb 27278 default:
Marko Mikulicic 0:c0ecb8bf28eb 27279 SLRE_THROW(e, SLRE_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 27280 }
Marko Mikulicic 0:c0ecb8bf28eb 27281
Marko Mikulicic 0:c0ecb8bf28eb 27282 switch (e->lookahead) {
Marko Mikulicic 0:c0ecb8bf28eb 27283 case '*':
Marko Mikulicic 0:c0ecb8bf28eb 27284 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27285 return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, SLRE_MAX_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27286 case '+':
Marko Mikulicic 0:c0ecb8bf28eb 27287 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27288 return re_nrep(e, nd, RE_ACCEPT(e, '?'), 1, SLRE_MAX_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27289 case '?':
Marko Mikulicic 0:c0ecb8bf28eb 27290 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27291 return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 27292 case L_COUNT:
Marko Mikulicic 0:c0ecb8bf28eb 27293 min = e->min_rep, max = e->max_rep;
Marko Mikulicic 0:c0ecb8bf28eb 27294 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27295 if (max < min) {
Marko Mikulicic 0:c0ecb8bf28eb 27296 SLRE_THROW(e, SLRE_INVALID_QUANTIFIER);
Marko Mikulicic 0:c0ecb8bf28eb 27297 }
Marko Mikulicic 0:c0ecb8bf28eb 27298 return re_nrep(e, nd, RE_ACCEPT(e, '?'), min, max);
Marko Mikulicic 0:c0ecb8bf28eb 27299 }
Marko Mikulicic 0:c0ecb8bf28eb 27300 return nd;
Marko Mikulicic 0:c0ecb8bf28eb 27301 }
Marko Mikulicic 0:c0ecb8bf28eb 27302
Marko Mikulicic 0:c0ecb8bf28eb 27303 static unsigned char re_endofcat(Rune c, int is_regex) {
Marko Mikulicic 0:c0ecb8bf28eb 27304 switch (c) {
Marko Mikulicic 0:c0ecb8bf28eb 27305 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27306 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27307 case '|':
Marko Mikulicic 0:c0ecb8bf28eb 27308 case ')':
Marko Mikulicic 0:c0ecb8bf28eb 27309 if (is_regex) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27310 }
Marko Mikulicic 0:c0ecb8bf28eb 27311 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27312 }
Marko Mikulicic 0:c0ecb8bf28eb 27313
Marko Mikulicic 0:c0ecb8bf28eb 27314 static struct slre_node *re_parser(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 27315 struct slre_node *alt = NULL, *cat, *nd;
Marko Mikulicic 0:c0ecb8bf28eb 27316 if (!re_endofcat(e->lookahead, e->is_regex)) {
Marko Mikulicic 0:c0ecb8bf28eb 27317 cat = re_parse_la(e);
Marko Mikulicic 0:c0ecb8bf28eb 27318 while (!re_endofcat(e->lookahead, e->is_regex)) {
Marko Mikulicic 0:c0ecb8bf28eb 27319 nd = cat;
Marko Mikulicic 0:c0ecb8bf28eb 27320 cat = re_nnode(e, P_CAT);
Marko Mikulicic 0:c0ecb8bf28eb 27321 cat->par.xy.x = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27322 cat->par.xy.y.y = re_parse_la(e);
Marko Mikulicic 0:c0ecb8bf28eb 27323 }
Marko Mikulicic 0:c0ecb8bf28eb 27324 alt = cat;
Marko Mikulicic 0:c0ecb8bf28eb 27325 }
Marko Mikulicic 0:c0ecb8bf28eb 27326 if (e->lookahead == '|') {
Marko Mikulicic 0:c0ecb8bf28eb 27327 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27328 nd = alt;
Marko Mikulicic 0:c0ecb8bf28eb 27329 alt = re_nnode(e, P_ALT);
Marko Mikulicic 0:c0ecb8bf28eb 27330 alt->par.xy.x = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27331 alt->par.xy.y.y = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27332 }
Marko Mikulicic 0:c0ecb8bf28eb 27333 return alt;
Marko Mikulicic 0:c0ecb8bf28eb 27334 }
Marko Mikulicic 0:c0ecb8bf28eb 27335
Marko Mikulicic 0:c0ecb8bf28eb 27336 static unsigned int re_nodelen(struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27337 unsigned int n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27338 if (!nd) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27339 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27340 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27341 n = 2;
Marko Mikulicic 0:c0ecb8bf28eb 27342 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27343 return re_nodelen(nd->par.xy.x) + re_nodelen(nd->par.xy.y.y) + n;
Marko Mikulicic 0:c0ecb8bf28eb 27344 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27345 case P_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27346 case P_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27347 return re_nodelen(nd->par.xy.x) + 2;
Marko Mikulicic 0:c0ecb8bf28eb 27348 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27349 n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27350 switch (nd->par.xy.y.rp.min) {
Marko Mikulicic 0:c0ecb8bf28eb 27351 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27352 if (!n) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27353 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP)
Marko Mikulicic 0:c0ecb8bf28eb 27354 return re_nodelen(nd->par.xy.x) + 2;
Marko Mikulicic 0:c0ecb8bf28eb 27355 case 1:
Marko Mikulicic 0:c0ecb8bf28eb 27356 if (!n) return re_nodelen(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27357 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP)
Marko Mikulicic 0:c0ecb8bf28eb 27358 return re_nodelen(nd->par.xy.x) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27359 default:
Marko Mikulicic 0:c0ecb8bf28eb 27360 n = 4;
Marko Mikulicic 0:c0ecb8bf28eb 27361 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) n++;
Marko Mikulicic 0:c0ecb8bf28eb 27362 return re_nodelen(nd->par.xy.x) + n;
Marko Mikulicic 0:c0ecb8bf28eb 27363 }
Marko Mikulicic 0:c0ecb8bf28eb 27364 default:
Marko Mikulicic 0:c0ecb8bf28eb 27365 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27366 }
Marko Mikulicic 0:c0ecb8bf28eb 27367 }
Marko Mikulicic 0:c0ecb8bf28eb 27368
Marko Mikulicic 0:c0ecb8bf28eb 27369 static struct slre_instruction *re_newinst(struct slre_prog *prog, int opcode) {
Marko Mikulicic 0:c0ecb8bf28eb 27370 memset(prog->end, 0, sizeof(struct slre_instruction));
Marko Mikulicic 0:c0ecb8bf28eb 27371 prog->end->opcode = opcode;
Marko Mikulicic 0:c0ecb8bf28eb 27372 return prog->end++;
Marko Mikulicic 0:c0ecb8bf28eb 27373 }
Marko Mikulicic 0:c0ecb8bf28eb 27374
Marko Mikulicic 0:c0ecb8bf28eb 27375 static void re_compile(struct slre_env *e, struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27376 struct slre_instruction *inst, *split, *jump, *rep;
Marko Mikulicic 0:c0ecb8bf28eb 27377 unsigned int n;
Marko Mikulicic 0:c0ecb8bf28eb 27378
Marko Mikulicic 0:c0ecb8bf28eb 27379 if (!nd) return;
Marko Mikulicic 0:c0ecb8bf28eb 27380
Marko Mikulicic 0:c0ecb8bf28eb 27381 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27382 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27383 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27384 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27385 jump = re_newinst(e->prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27386 re_compile(e, nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27387 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27388 split->par.xy.y.y = jump + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27389 jump->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27390 break;
Marko Mikulicic 0:c0ecb8bf28eb 27391
Marko Mikulicic 0:c0ecb8bf28eb 27392 case P_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27393 re_newinst(e->prog, I_ANY);
Marko Mikulicic 0:c0ecb8bf28eb 27394 break;
Marko Mikulicic 0:c0ecb8bf28eb 27395
Marko Mikulicic 0:c0ecb8bf28eb 27396 case P_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27397 re_newinst(e->prog, I_BOL);
Marko Mikulicic 0:c0ecb8bf28eb 27398 break;
Marko Mikulicic 0:c0ecb8bf28eb 27399
Marko Mikulicic 0:c0ecb8bf28eb 27400 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27401 inst = re_newinst(e->prog, I_LBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27402 inst->par.n = nd->par.xy.y.n;
Marko Mikulicic 0:c0ecb8bf28eb 27403 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27404 inst = re_newinst(e->prog, I_RBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27405 inst->par.n = nd->par.xy.y.n;
Marko Mikulicic 0:c0ecb8bf28eb 27406 break;
Marko Mikulicic 0:c0ecb8bf28eb 27407
Marko Mikulicic 0:c0ecb8bf28eb 27408 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27409 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27410 re_compile(e, nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27411 break;
Marko Mikulicic 0:c0ecb8bf28eb 27412
Marko Mikulicic 0:c0ecb8bf28eb 27413 case P_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27414 inst = re_newinst(e->prog, I_CH);
Marko Mikulicic 0:c0ecb8bf28eb 27415 inst->par.c = nd->par.c;
Marko Mikulicic 0:c0ecb8bf28eb 27416 break;
Marko Mikulicic 0:c0ecb8bf28eb 27417
Marko Mikulicic 0:c0ecb8bf28eb 27418 case P_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27419 re_newinst(e->prog, I_EOL);
Marko Mikulicic 0:c0ecb8bf28eb 27420 break;
Marko Mikulicic 0:c0ecb8bf28eb 27421
Marko Mikulicic 0:c0ecb8bf28eb 27422 case P_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27423 re_newinst(e->prog, I_EOS);
Marko Mikulicic 0:c0ecb8bf28eb 27424 break;
Marko Mikulicic 0:c0ecb8bf28eb 27425
Marko Mikulicic 0:c0ecb8bf28eb 27426 case P_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27427 split = re_newinst(e->prog, I_LA);
Marko Mikulicic 0:c0ecb8bf28eb 27428 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27429 re_newinst(e->prog, I_END);
Marko Mikulicic 0:c0ecb8bf28eb 27430 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27431 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27432 break;
Marko Mikulicic 0:c0ecb8bf28eb 27433 case P_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27434 split = re_newinst(e->prog, I_LA_N);
Marko Mikulicic 0:c0ecb8bf28eb 27435 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27436 re_newinst(e->prog, I_END);
Marko Mikulicic 0:c0ecb8bf28eb 27437 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27438 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27439 break;
Marko Mikulicic 0:c0ecb8bf28eb 27440
Marko Mikulicic 0:c0ecb8bf28eb 27441 case P_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27442 inst = re_newinst(e->prog, I_REF);
Marko Mikulicic 0:c0ecb8bf28eb 27443 inst->par.n = nd->par.xy.y.n;
Marko Mikulicic 0:c0ecb8bf28eb 27444 break;
Marko Mikulicic 0:c0ecb8bf28eb 27445
Marko Mikulicic 0:c0ecb8bf28eb 27446 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27447 n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27448 switch (nd->par.xy.y.rp.min) {
Marko Mikulicic 0:c0ecb8bf28eb 27449 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27450 if (!n) break;
Marko Mikulicic 0:c0ecb8bf28eb 27451 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
Marko Mikulicic 0:c0ecb8bf28eb 27452 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27453 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27454 jump = re_newinst(e->prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27455 jump->par.xy.x = split;
Marko Mikulicic 0:c0ecb8bf28eb 27456 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27457 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27458 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27459 split->par.xy.y.y = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27460 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27461 }
Marko Mikulicic 0:c0ecb8bf28eb 27462 break;
Marko Mikulicic 0:c0ecb8bf28eb 27463 }
Marko Mikulicic 0:c0ecb8bf28eb 27464 case 1:
Marko Mikulicic 0:c0ecb8bf28eb 27465 if (!n) {
Marko Mikulicic 0:c0ecb8bf28eb 27466 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27467 break;
Marko Mikulicic 0:c0ecb8bf28eb 27468 }
Marko Mikulicic 0:c0ecb8bf28eb 27469 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
Marko Mikulicic 0:c0ecb8bf28eb 27470 inst = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27471 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27472 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27473 split->par.xy.x = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27474 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27475 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27476 split->par.xy.y.y = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27477 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27478 }
Marko Mikulicic 0:c0ecb8bf28eb 27479 break;
Marko Mikulicic 0:c0ecb8bf28eb 27480 }
Marko Mikulicic 0:c0ecb8bf28eb 27481 default:
Marko Mikulicic 0:c0ecb8bf28eb 27482 inst = re_newinst(e->prog, I_REP_INI);
Marko Mikulicic 0:c0ecb8bf28eb 27483 inst->par.xy.y.rp.min = nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27484 inst->par.xy.y.rp.max = n;
Marko Mikulicic 0:c0ecb8bf28eb 27485 rep = re_newinst(e->prog, I_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27486 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27487 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27488 jump = re_newinst(e->prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27489 jump->par.xy.x = rep;
Marko Mikulicic 0:c0ecb8bf28eb 27490 rep->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27491 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27492 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27493 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27494 split->par.xy.y.y = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27495 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27496 }
Marko Mikulicic 0:c0ecb8bf28eb 27497 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
Marko Mikulicic 0:c0ecb8bf28eb 27498 inst = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27499 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27500 split->par.xy.x = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27501 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27502 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27503 split->par.xy.y.y = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27504 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27505 }
Marko Mikulicic 0:c0ecb8bf28eb 27506 break;
Marko Mikulicic 0:c0ecb8bf28eb 27507 }
Marko Mikulicic 0:c0ecb8bf28eb 27508 break;
Marko Mikulicic 0:c0ecb8bf28eb 27509 }
Marko Mikulicic 0:c0ecb8bf28eb 27510 break;
Marko Mikulicic 0:c0ecb8bf28eb 27511
Marko Mikulicic 0:c0ecb8bf28eb 27512 case P_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27513 inst = re_newinst(e->prog, I_SET);
Marko Mikulicic 0:c0ecb8bf28eb 27514 inst->par.cp = nd->par.cp;
Marko Mikulicic 0:c0ecb8bf28eb 27515 break;
Marko Mikulicic 0:c0ecb8bf28eb 27516 case P_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27517 inst = re_newinst(e->prog, I_SET_N);
Marko Mikulicic 0:c0ecb8bf28eb 27518 inst->par.cp = nd->par.cp;
Marko Mikulicic 0:c0ecb8bf28eb 27519 break;
Marko Mikulicic 0:c0ecb8bf28eb 27520
Marko Mikulicic 0:c0ecb8bf28eb 27521 case P_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27522 re_newinst(e->prog, I_WORD);
Marko Mikulicic 0:c0ecb8bf28eb 27523 break;
Marko Mikulicic 0:c0ecb8bf28eb 27524 case P_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27525 re_newinst(e->prog, I_WORD_N);
Marko Mikulicic 0:c0ecb8bf28eb 27526 break;
Marko Mikulicic 0:c0ecb8bf28eb 27527 }
Marko Mikulicic 0:c0ecb8bf28eb 27528 }
Marko Mikulicic 0:c0ecb8bf28eb 27529
Marko Mikulicic 0:c0ecb8bf28eb 27530 #ifdef RE_TEST
Marko Mikulicic 0:c0ecb8bf28eb 27531 static void print_set(struct slre_class *cp) {
Marko Mikulicic 0:c0ecb8bf28eb 27532 struct slre_range *p;
Marko Mikulicic 0:c0ecb8bf28eb 27533 for (p = cp->spans; p < cp->end; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 27534 printf("%s", p == cp->spans ? "'" : ",'");
Marko Mikulicic 0:c0ecb8bf28eb 27535 printf(
Marko Mikulicic 0:c0ecb8bf28eb 27536 p->s >= 32 && p->s < 127 ? "%c" : (p->s < 256 ? "\\x%02X" : "\\u%04X"),
Marko Mikulicic 0:c0ecb8bf28eb 27537 p->s);
Marko Mikulicic 0:c0ecb8bf28eb 27538 if (p->s != p->e) {
Marko Mikulicic 0:c0ecb8bf28eb 27539 printf(p->e >= 32 && p->e < 127 ? "-%c"
Marko Mikulicic 0:c0ecb8bf28eb 27540 : (p->e < 256 ? "-\\x%02X" : "-\\u%04X"),
Marko Mikulicic 0:c0ecb8bf28eb 27541 p->e);
Marko Mikulicic 0:c0ecb8bf28eb 27542 }
Marko Mikulicic 0:c0ecb8bf28eb 27543 printf("'");
Marko Mikulicic 0:c0ecb8bf28eb 27544 }
Marko Mikulicic 0:c0ecb8bf28eb 27545 printf("]");
Marko Mikulicic 0:c0ecb8bf28eb 27546 }
Marko Mikulicic 0:c0ecb8bf28eb 27547
Marko Mikulicic 0:c0ecb8bf28eb 27548 static void node_print(struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27549 if (!nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27550 printf("Empty");
Marko Mikulicic 0:c0ecb8bf28eb 27551 return;
Marko Mikulicic 0:c0ecb8bf28eb 27552 }
Marko Mikulicic 0:c0ecb8bf28eb 27553 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27554 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27555 printf("{");
Marko Mikulicic 0:c0ecb8bf28eb 27556 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27557 printf(" | ");
Marko Mikulicic 0:c0ecb8bf28eb 27558 node_print(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27559 printf("}");
Marko Mikulicic 0:c0ecb8bf28eb 27560 break;
Marko Mikulicic 0:c0ecb8bf28eb 27561 case P_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27562 printf(".");
Marko Mikulicic 0:c0ecb8bf28eb 27563 break;
Marko Mikulicic 0:c0ecb8bf28eb 27564 case P_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27565 printf("^");
Marko Mikulicic 0:c0ecb8bf28eb 27566 break;
Marko Mikulicic 0:c0ecb8bf28eb 27567 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27568 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27569 printf(")");
Marko Mikulicic 0:c0ecb8bf28eb 27570 break;
Marko Mikulicic 0:c0ecb8bf28eb 27571 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27572 printf("{");
Marko Mikulicic 0:c0ecb8bf28eb 27573 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27574 printf(" & ");
Marko Mikulicic 0:c0ecb8bf28eb 27575 node_print(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27576 printf("}");
Marko Mikulicic 0:c0ecb8bf28eb 27577 break;
Marko Mikulicic 0:c0ecb8bf28eb 27578 case P_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27579 printf(nd->par.c >= 32 && nd->par.c < 127 ? "'%c'" : "'\\u%04X'",
Marko Mikulicic 0:c0ecb8bf28eb 27580 nd->par.c);
Marko Mikulicic 0:c0ecb8bf28eb 27581 break;
Marko Mikulicic 0:c0ecb8bf28eb 27582 case P_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27583 printf("$");
Marko Mikulicic 0:c0ecb8bf28eb 27584 break;
Marko Mikulicic 0:c0ecb8bf28eb 27585 case P_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27586 printf("\\0");
Marko Mikulicic 0:c0ecb8bf28eb 27587 break;
Marko Mikulicic 0:c0ecb8bf28eb 27588 case P_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27589 printf("LA(");
Marko Mikulicic 0:c0ecb8bf28eb 27590 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27591 printf(")");
Marko Mikulicic 0:c0ecb8bf28eb 27592 break;
Marko Mikulicic 0:c0ecb8bf28eb 27593 case P_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27594 printf("LA_N(");
Marko Mikulicic 0:c0ecb8bf28eb 27595 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27596 printf(")");
Marko Mikulicic 0:c0ecb8bf28eb 27597 break;
Marko Mikulicic 0:c0ecb8bf28eb 27598 case P_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27599 printf("\\%d", nd->par.xy.y.n);
Marko Mikulicic 0:c0ecb8bf28eb 27600 break;
Marko Mikulicic 0:c0ecb8bf28eb 27601 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27602 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27603 printf(nd->par.xy.y.rp.ng ? "{%d,%d}?" : "{%d,%d}", nd->par.xy.y.rp.min,
Marko Mikulicic 0:c0ecb8bf28eb 27604 nd->par.xy.y.rp.max);
Marko Mikulicic 0:c0ecb8bf28eb 27605 break;
Marko Mikulicic 0:c0ecb8bf28eb 27606 case P_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27607 printf("[");
Marko Mikulicic 0:c0ecb8bf28eb 27608 print_set(nd->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27609 break;
Marko Mikulicic 0:c0ecb8bf28eb 27610 case P_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27611 printf("[^");
Marko Mikulicic 0:c0ecb8bf28eb 27612 print_set(nd->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27613 break;
Marko Mikulicic 0:c0ecb8bf28eb 27614 case P_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27615 printf("\\b");
Marko Mikulicic 0:c0ecb8bf28eb 27616 break;
Marko Mikulicic 0:c0ecb8bf28eb 27617 case P_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27618 printf("\\B");
Marko Mikulicic 0:c0ecb8bf28eb 27619 break;
Marko Mikulicic 0:c0ecb8bf28eb 27620 }
Marko Mikulicic 0:c0ecb8bf28eb 27621 }
Marko Mikulicic 0:c0ecb8bf28eb 27622
Marko Mikulicic 0:c0ecb8bf28eb 27623 static void program_print(struct slre_prog *prog) {
Marko Mikulicic 0:c0ecb8bf28eb 27624 struct slre_instruction *inst;
Marko Mikulicic 0:c0ecb8bf28eb 27625 for (inst = prog->start; inst < prog->end; ++inst) {
Marko Mikulicic 0:c0ecb8bf28eb 27626 printf("%3d: ", inst - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27627 switch (inst->opcode) {
Marko Mikulicic 0:c0ecb8bf28eb 27628 case I_END:
Marko Mikulicic 0:c0ecb8bf28eb 27629 puts("end");
Marko Mikulicic 0:c0ecb8bf28eb 27630 break;
Marko Mikulicic 0:c0ecb8bf28eb 27631 case I_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27632 puts(".");
Marko Mikulicic 0:c0ecb8bf28eb 27633 break;
Marko Mikulicic 0:c0ecb8bf28eb 27634 case I_ANYNL:
Marko Mikulicic 0:c0ecb8bf28eb 27635 puts(". | '\\r' | '\\n'");
Marko Mikulicic 0:c0ecb8bf28eb 27636 break;
Marko Mikulicic 0:c0ecb8bf28eb 27637 case I_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27638 puts("^");
Marko Mikulicic 0:c0ecb8bf28eb 27639 break;
Marko Mikulicic 0:c0ecb8bf28eb 27640 case I_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27641 printf(
Marko Mikulicic 0:c0ecb8bf28eb 27642 inst->par.c >= 32 && inst->par.c < 127 ? "'%c'\n" : "'\\u%04X'\n",
Marko Mikulicic 0:c0ecb8bf28eb 27643 inst->par.c);
Marko Mikulicic 0:c0ecb8bf28eb 27644 break;
Marko Mikulicic 0:c0ecb8bf28eb 27645 case I_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27646 puts("$");
Marko Mikulicic 0:c0ecb8bf28eb 27647 break;
Marko Mikulicic 0:c0ecb8bf28eb 27648 case I_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27649 puts("\\0");
Marko Mikulicic 0:c0ecb8bf28eb 27650 break;
Marko Mikulicic 0:c0ecb8bf28eb 27651 case I_JUMP:
Marko Mikulicic 0:c0ecb8bf28eb 27652 printf("-->%d\n", inst->par.xy.x - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27653 break;
Marko Mikulicic 0:c0ecb8bf28eb 27654 case I_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27655 printf("la %d %d\n", inst->par.xy.x - prog->start,
Marko Mikulicic 0:c0ecb8bf28eb 27656 inst->par.xy.y.y - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27657 break;
Marko Mikulicic 0:c0ecb8bf28eb 27658 case I_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27659 printf("la_n %d %d\n", inst->par.xy.x - prog->start,
Marko Mikulicic 0:c0ecb8bf28eb 27660 inst->par.xy.y.y - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27661 break;
Marko Mikulicic 0:c0ecb8bf28eb 27662 case I_LBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27663 printf("( %d\n", inst->par.n);
Marko Mikulicic 0:c0ecb8bf28eb 27664 break;
Marko Mikulicic 0:c0ecb8bf28eb 27665 case I_RBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27666 printf(") %d\n", inst->par.n);
Marko Mikulicic 0:c0ecb8bf28eb 27667 break;
Marko Mikulicic 0:c0ecb8bf28eb 27668 case I_SPLIT:
Marko Mikulicic 0:c0ecb8bf28eb 27669 printf("-->%d | -->%d\n", inst->par.xy.x - prog->start,
Marko Mikulicic 0:c0ecb8bf28eb 27670 inst->par.xy.y.y - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27671 break;
Marko Mikulicic 0:c0ecb8bf28eb 27672 case I_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27673 printf("\\%d\n", inst->par.n);
Marko Mikulicic 0:c0ecb8bf28eb 27674 break;
Marko Mikulicic 0:c0ecb8bf28eb 27675 case I_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27676 printf("repeat -->%d\n", inst->par.xy.x - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27677 break;
Marko Mikulicic 0:c0ecb8bf28eb 27678 case I_REP_INI:
Marko Mikulicic 0:c0ecb8bf28eb 27679 printf("init_rep %d %d\n", inst->par.xy.y.rp.min,
Marko Mikulicic 0:c0ecb8bf28eb 27680 inst->par.xy.y.rp.min + inst->par.xy.y.rp.max);
Marko Mikulicic 0:c0ecb8bf28eb 27681 break;
Marko Mikulicic 0:c0ecb8bf28eb 27682 case I_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27683 printf("[");
Marko Mikulicic 0:c0ecb8bf28eb 27684 print_set(inst->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27685 puts("");
Marko Mikulicic 0:c0ecb8bf28eb 27686 break;
Marko Mikulicic 0:c0ecb8bf28eb 27687 case I_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27688 printf("[^");
Marko Mikulicic 0:c0ecb8bf28eb 27689 print_set(inst->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27690 puts("");
Marko Mikulicic 0:c0ecb8bf28eb 27691 break;
Marko Mikulicic 0:c0ecb8bf28eb 27692 case I_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27693 puts("\\w");
Marko Mikulicic 0:c0ecb8bf28eb 27694 break;
Marko Mikulicic 0:c0ecb8bf28eb 27695 case I_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27696 puts("\\W");
Marko Mikulicic 0:c0ecb8bf28eb 27697 break;
Marko Mikulicic 0:c0ecb8bf28eb 27698 }
Marko Mikulicic 0:c0ecb8bf28eb 27699 }
Marko Mikulicic 0:c0ecb8bf28eb 27700 }
Marko Mikulicic 0:c0ecb8bf28eb 27701 #endif
Marko Mikulicic 0:c0ecb8bf28eb 27702
Marko Mikulicic 0:c0ecb8bf28eb 27703 int slre_compile(const char *pat, size_t pat_len, const char *flags,
Marko Mikulicic 0:c0ecb8bf28eb 27704 volatile size_t fl_len, struct slre_prog **pr, int is_regex) {
Marko Mikulicic 0:c0ecb8bf28eb 27705 struct slre_env e;
Marko Mikulicic 0:c0ecb8bf28eb 27706 struct slre_node *nd;
Marko Mikulicic 0:c0ecb8bf28eb 27707 struct slre_instruction *split, *jump;
Marko Mikulicic 0:c0ecb8bf28eb 27708 int err_code;
Marko Mikulicic 0:c0ecb8bf28eb 27709
Marko Mikulicic 0:c0ecb8bf28eb 27710 e.is_regex = is_regex;
Marko Mikulicic 0:c0ecb8bf28eb 27711 e.prog = (struct slre_prog *) SLRE_MALLOC(sizeof(struct slre_prog));
Marko Mikulicic 0:c0ecb8bf28eb 27712 e.pstart = e.pend =
Marko Mikulicic 0:c0ecb8bf28eb 27713 (struct slre_node *) SLRE_MALLOC(sizeof(struct slre_node) * pat_len * 2);
Marko Mikulicic 0:c0ecb8bf28eb 27714 e.prog->flags = is_regex ? SLRE_FLAG_RE : 0;
Marko Mikulicic 0:c0ecb8bf28eb 27715
Marko Mikulicic 0:c0ecb8bf28eb 27716 if ((err_code = setjmp(e.jmp_buf)) != SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 27717 SLRE_FREE(e.pstart);
Marko Mikulicic 0:c0ecb8bf28eb 27718 SLRE_FREE(e.prog);
Marko Mikulicic 0:c0ecb8bf28eb 27719 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 27720 }
Marko Mikulicic 0:c0ecb8bf28eb 27721
Marko Mikulicic 0:c0ecb8bf28eb 27722 while (fl_len--) {
Marko Mikulicic 0:c0ecb8bf28eb 27723 switch (flags[fl_len]) {
Marko Mikulicic 0:c0ecb8bf28eb 27724 case 'g':
Marko Mikulicic 0:c0ecb8bf28eb 27725 e.prog->flags |= SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 27726 break;
Marko Mikulicic 0:c0ecb8bf28eb 27727 case 'i':
Marko Mikulicic 0:c0ecb8bf28eb 27728 e.prog->flags |= SLRE_FLAG_I;
Marko Mikulicic 0:c0ecb8bf28eb 27729 break;
Marko Mikulicic 0:c0ecb8bf28eb 27730 case 'm':
Marko Mikulicic 0:c0ecb8bf28eb 27731 e.prog->flags |= SLRE_FLAG_M;
Marko Mikulicic 0:c0ecb8bf28eb 27732 break;
Marko Mikulicic 0:c0ecb8bf28eb 27733 }
Marko Mikulicic 0:c0ecb8bf28eb 27734 }
Marko Mikulicic 0:c0ecb8bf28eb 27735
Marko Mikulicic 0:c0ecb8bf28eb 27736 e.src = pat;
Marko Mikulicic 0:c0ecb8bf28eb 27737 e.src_end = pat + pat_len;
Marko Mikulicic 0:c0ecb8bf28eb 27738 e.sets_num = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27739 e.num_captures = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27740 /*e.flags = flags;*/
Marko Mikulicic 0:c0ecb8bf28eb 27741 memset(e.caps, 0, sizeof(e.caps));
Marko Mikulicic 0:c0ecb8bf28eb 27742
Marko Mikulicic 0:c0ecb8bf28eb 27743 RE_NEXT(&e);
Marko Mikulicic 0:c0ecb8bf28eb 27744 nd = re_parser(&e);
Marko Mikulicic 0:c0ecb8bf28eb 27745 if (e.lookahead == ')') {
Marko Mikulicic 0:c0ecb8bf28eb 27746 SLRE_THROW(&e, SLRE_UNMATCH_RBR);
Marko Mikulicic 0:c0ecb8bf28eb 27747 }
Marko Mikulicic 0:c0ecb8bf28eb 27748 if (e.lookahead != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 27749 SLRE_THROW(&e, SLRE_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 27750 }
Marko Mikulicic 0:c0ecb8bf28eb 27751
Marko Mikulicic 0:c0ecb8bf28eb 27752 e.prog->num_captures = e.num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 27753 e.prog->start = e.prog->end = (struct slre_instruction *) SLRE_MALLOC(
Marko Mikulicic 0:c0ecb8bf28eb 27754 (re_nodelen(nd) + 6) * sizeof(struct slre_instruction));
Marko Mikulicic 0:c0ecb8bf28eb 27755
Marko Mikulicic 0:c0ecb8bf28eb 27756 split = re_newinst(e.prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27757 split->par.xy.x = split + 3;
Marko Mikulicic 0:c0ecb8bf28eb 27758 split->par.xy.y.y = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27759 re_newinst(e.prog, I_ANYNL);
Marko Mikulicic 0:c0ecb8bf28eb 27760 jump = re_newinst(e.prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27761 jump->par.xy.x = split;
Marko Mikulicic 0:c0ecb8bf28eb 27762 re_newinst(e.prog, I_LBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27763 re_compile(&e, nd);
Marko Mikulicic 0:c0ecb8bf28eb 27764 re_newinst(e.prog, I_RBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27765 re_newinst(e.prog, I_END);
Marko Mikulicic 0:c0ecb8bf28eb 27766
Marko Mikulicic 0:c0ecb8bf28eb 27767 #ifdef RE_TEST
Marko Mikulicic 0:c0ecb8bf28eb 27768 node_print(nd);
Marko Mikulicic 0:c0ecb8bf28eb 27769 putchar('\n');
Marko Mikulicic 0:c0ecb8bf28eb 27770 program_print(e.prog);
Marko Mikulicic 0:c0ecb8bf28eb 27771 #endif
Marko Mikulicic 0:c0ecb8bf28eb 27772
Marko Mikulicic 0:c0ecb8bf28eb 27773 SLRE_FREE(e.pstart);
Marko Mikulicic 0:c0ecb8bf28eb 27774
Marko Mikulicic 0:c0ecb8bf28eb 27775 if (pr != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 27776 *pr = e.prog;
Marko Mikulicic 0:c0ecb8bf28eb 27777 } else {
Marko Mikulicic 0:c0ecb8bf28eb 27778 slre_free(e.prog);
Marko Mikulicic 0:c0ecb8bf28eb 27779 }
Marko Mikulicic 0:c0ecb8bf28eb 27780
Marko Mikulicic 0:c0ecb8bf28eb 27781 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 27782 }
Marko Mikulicic 0:c0ecb8bf28eb 27783
Marko Mikulicic 0:c0ecb8bf28eb 27784 void slre_free(struct slre_prog *prog) {
Marko Mikulicic 0:c0ecb8bf28eb 27785 if (prog) {
Marko Mikulicic 0:c0ecb8bf28eb 27786 SLRE_FREE(prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27787 SLRE_FREE(prog);
Marko Mikulicic 0:c0ecb8bf28eb 27788 }
Marko Mikulicic 0:c0ecb8bf28eb 27789 }
Marko Mikulicic 0:c0ecb8bf28eb 27790
Marko Mikulicic 0:c0ecb8bf28eb 27791 static struct slre_thread *re_newthread(struct slre_thread *t,
Marko Mikulicic 0:c0ecb8bf28eb 27792 struct slre_instruction *pc,
Marko Mikulicic 0:c0ecb8bf28eb 27793 const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 27794 struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 27795 struct slre_thread *new_thread =
Marko Mikulicic 0:c0ecb8bf28eb 27796 (struct slre_thread *) SLRE_MALLOC(sizeof(struct slre_thread));
Marko Mikulicic 0:c0ecb8bf28eb 27797 if (new_thread != NULL) new_thread->prev = t;
Marko Mikulicic 0:c0ecb8bf28eb 27798 t->pc = pc;
Marko Mikulicic 0:c0ecb8bf28eb 27799 t->start = start;
Marko Mikulicic 0:c0ecb8bf28eb 27800 t->loot = *loot;
Marko Mikulicic 0:c0ecb8bf28eb 27801 return new_thread;
Marko Mikulicic 0:c0ecb8bf28eb 27802 }
Marko Mikulicic 0:c0ecb8bf28eb 27803
Marko Mikulicic 0:c0ecb8bf28eb 27804 static struct slre_thread *get_prev_thread(struct slre_thread *t) {
Marko Mikulicic 0:c0ecb8bf28eb 27805 struct slre_thread *tmp_thr = t->prev;
Marko Mikulicic 0:c0ecb8bf28eb 27806 SLRE_FREE(t);
Marko Mikulicic 0:c0ecb8bf28eb 27807 return tmp_thr;
Marko Mikulicic 0:c0ecb8bf28eb 27808 }
Marko Mikulicic 0:c0ecb8bf28eb 27809
Marko Mikulicic 0:c0ecb8bf28eb 27810 static void free_threads(struct slre_thread *t) {
Marko Mikulicic 0:c0ecb8bf28eb 27811 while (t->prev != NULL) t = get_prev_thread(t);
Marko Mikulicic 0:c0ecb8bf28eb 27812 }
Marko Mikulicic 0:c0ecb8bf28eb 27813
Marko Mikulicic 0:c0ecb8bf28eb 27814 static unsigned char re_match(struct slre_instruction *pc, const char *current,
Marko Mikulicic 0:c0ecb8bf28eb 27815 const char *end, const char *bol,
Marko Mikulicic 0:c0ecb8bf28eb 27816 unsigned int flags, struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 27817 struct slre_loot sub, tmpsub;
Marko Mikulicic 0:c0ecb8bf28eb 27818 Rune c, r;
Marko Mikulicic 0:c0ecb8bf28eb 27819 struct slre_range *p;
Marko Mikulicic 0:c0ecb8bf28eb 27820 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 27821 struct slre_thread thread, *curr_thread, *tmp_thr;
Marko Mikulicic 0:c0ecb8bf28eb 27822
Marko Mikulicic 0:c0ecb8bf28eb 27823 /* queue initial thread */
Marko Mikulicic 0:c0ecb8bf28eb 27824 thread.prev = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 27825 curr_thread = re_newthread(&thread, pc, current, loot);
Marko Mikulicic 0:c0ecb8bf28eb 27826
Marko Mikulicic 0:c0ecb8bf28eb 27827 /* run threads in stack order */
Marko Mikulicic 0:c0ecb8bf28eb 27828 do {
Marko Mikulicic 0:c0ecb8bf28eb 27829 curr_thread = get_prev_thread(curr_thread);
Marko Mikulicic 0:c0ecb8bf28eb 27830 pc = curr_thread->pc;
Marko Mikulicic 0:c0ecb8bf28eb 27831 current = curr_thread->start;
Marko Mikulicic 0:c0ecb8bf28eb 27832 sub = curr_thread->loot;
Marko Mikulicic 0:c0ecb8bf28eb 27833 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 27834 switch (pc->opcode) {
Marko Mikulicic 0:c0ecb8bf28eb 27835 case I_END:
Marko Mikulicic 0:c0ecb8bf28eb 27836 memcpy(loot->caps, sub.caps, sizeof loot->caps);
Marko Mikulicic 0:c0ecb8bf28eb 27837 free_threads(curr_thread);
Marko Mikulicic 0:c0ecb8bf28eb 27838 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27839 case I_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27840 case I_ANYNL:
Marko Mikulicic 0:c0ecb8bf28eb 27841 if (current < end) {
Marko Mikulicic 0:c0ecb8bf28eb 27842 current += chartorune(&c, current);
Marko Mikulicic 0:c0ecb8bf28eb 27843 if (c && !(pc->opcode == I_ANY && isnewline(c))) break;
Marko Mikulicic 0:c0ecb8bf28eb 27844 }
Marko Mikulicic 0:c0ecb8bf28eb 27845 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27846
Marko Mikulicic 0:c0ecb8bf28eb 27847 case I_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27848 if (current == bol) break;
Marko Mikulicic 0:c0ecb8bf28eb 27849 if ((flags & SLRE_FLAG_M) && isnewline(current[-1])) break;
Marko Mikulicic 0:c0ecb8bf28eb 27850 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27851 case I_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27852 if (current < end) {
Marko Mikulicic 0:c0ecb8bf28eb 27853 current += chartorune(&c, current);
Marko Mikulicic 0:c0ecb8bf28eb 27854 if (c &&
Marko Mikulicic 0:c0ecb8bf28eb 27855 (c == pc->par.c || ((flags & SLRE_FLAG_I) &&
Marko Mikulicic 0:c0ecb8bf28eb 27856 tolowerrune(c) == tolowerrune(pc->par.c))))
Marko Mikulicic 0:c0ecb8bf28eb 27857 break;
Marko Mikulicic 0:c0ecb8bf28eb 27858 }
Marko Mikulicic 0:c0ecb8bf28eb 27859 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27860 case I_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27861 if (current >= end) break;
Marko Mikulicic 0:c0ecb8bf28eb 27862 if ((flags & SLRE_FLAG_M) && isnewline(*current)) break;
Marko Mikulicic 0:c0ecb8bf28eb 27863 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27864 case I_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27865 if (current >= end) break;
Marko Mikulicic 0:c0ecb8bf28eb 27866 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27867
Marko Mikulicic 0:c0ecb8bf28eb 27868 case I_JUMP:
Marko Mikulicic 0:c0ecb8bf28eb 27869 pc = pc->par.xy.x;
Marko Mikulicic 0:c0ecb8bf28eb 27870 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27871
Marko Mikulicic 0:c0ecb8bf28eb 27872 case I_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27873 if (re_match(pc->par.xy.x, current, end, bol, flags, &sub)) {
Marko Mikulicic 0:c0ecb8bf28eb 27874 pc = pc->par.xy.y.y;
Marko Mikulicic 0:c0ecb8bf28eb 27875 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27876 }
Marko Mikulicic 0:c0ecb8bf28eb 27877 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27878 case I_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27879 tmpsub = sub;
Marko Mikulicic 0:c0ecb8bf28eb 27880 if (!re_match(pc->par.xy.x, current, end, bol, flags, &tmpsub)) {
Marko Mikulicic 0:c0ecb8bf28eb 27881 pc = pc->par.xy.y.y;
Marko Mikulicic 0:c0ecb8bf28eb 27882 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27883 }
Marko Mikulicic 0:c0ecb8bf28eb 27884 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27885
Marko Mikulicic 0:c0ecb8bf28eb 27886 case I_LBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27887 sub.caps[pc->par.n].start = current;
Marko Mikulicic 0:c0ecb8bf28eb 27888 break;
Marko Mikulicic 0:c0ecb8bf28eb 27889
Marko Mikulicic 0:c0ecb8bf28eb 27890 case I_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27891 i = sub.caps[pc->par.n].end - sub.caps[pc->par.n].start;
Marko Mikulicic 0:c0ecb8bf28eb 27892 if (flags & SLRE_FLAG_I) {
Marko Mikulicic 0:c0ecb8bf28eb 27893 int num = i;
Marko Mikulicic 0:c0ecb8bf28eb 27894 const char *s = current, *p = sub.caps[pc->par.n].start;
Marko Mikulicic 0:c0ecb8bf28eb 27895 Rune rr;
Marko Mikulicic 0:c0ecb8bf28eb 27896 for (; num && *s && *p; num--) {
Marko Mikulicic 0:c0ecb8bf28eb 27897 s += chartorune(&r, s);
Marko Mikulicic 0:c0ecb8bf28eb 27898 p += chartorune(&rr, p);
Marko Mikulicic 0:c0ecb8bf28eb 27899 if (tolowerrune(r) != tolowerrune(rr)) break;
Marko Mikulicic 0:c0ecb8bf28eb 27900 }
Marko Mikulicic 0:c0ecb8bf28eb 27901 if (num) goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27902 } else if (strncmp(current, sub.caps[pc->par.n].start, i)) {
Marko Mikulicic 0:c0ecb8bf28eb 27903 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27904 }
Marko Mikulicic 0:c0ecb8bf28eb 27905 if (i > 0) current += i;
Marko Mikulicic 0:c0ecb8bf28eb 27906 break;
Marko Mikulicic 0:c0ecb8bf28eb 27907
Marko Mikulicic 0:c0ecb8bf28eb 27908 case I_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27909 if (pc->par.xy.y.rp.min) {
Marko Mikulicic 0:c0ecb8bf28eb 27910 pc->par.xy.y.rp.min--;
Marko Mikulicic 0:c0ecb8bf28eb 27911 pc++;
Marko Mikulicic 0:c0ecb8bf28eb 27912 } else if (!pc->par.xy.y.rp.max--) {
Marko Mikulicic 0:c0ecb8bf28eb 27913 pc = pc->par.xy.x;
Marko Mikulicic 0:c0ecb8bf28eb 27914 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27915 }
Marko Mikulicic 0:c0ecb8bf28eb 27916 break;
Marko Mikulicic 0:c0ecb8bf28eb 27917
Marko Mikulicic 0:c0ecb8bf28eb 27918 case I_REP_INI:
Marko Mikulicic 0:c0ecb8bf28eb 27919 (pc + 1)->par.xy.y.rp.min = pc->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27920 (pc + 1)->par.xy.y.rp.max = pc->par.xy.y.rp.max;
Marko Mikulicic 0:c0ecb8bf28eb 27921 break;
Marko Mikulicic 0:c0ecb8bf28eb 27922
Marko Mikulicic 0:c0ecb8bf28eb 27923 case I_RBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27924 sub.caps[pc->par.n].end = current;
Marko Mikulicic 0:c0ecb8bf28eb 27925 break;
Marko Mikulicic 0:c0ecb8bf28eb 27926
Marko Mikulicic 0:c0ecb8bf28eb 27927 case I_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27928 case I_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27929 if (current >= end) goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27930 current += chartorune(&c, current);
Marko Mikulicic 0:c0ecb8bf28eb 27931 if (!c) goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27932
Marko Mikulicic 0:c0ecb8bf28eb 27933 i = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27934 for (p = pc->par.cp->spans; i && p < pc->par.cp->end; p++)
Marko Mikulicic 0:c0ecb8bf28eb 27935 if (flags & SLRE_FLAG_I) {
Marko Mikulicic 0:c0ecb8bf28eb 27936 for (r = p->s; r <= p->e; ++r)
Marko Mikulicic 0:c0ecb8bf28eb 27937 if (tolowerrune(c) == tolowerrune(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 27938 i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27939 break;
Marko Mikulicic 0:c0ecb8bf28eb 27940 }
Marko Mikulicic 0:c0ecb8bf28eb 27941 } else if (p->s <= c && c <= p->e)
Marko Mikulicic 0:c0ecb8bf28eb 27942 i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27943
Marko Mikulicic 0:c0ecb8bf28eb 27944 if (pc->opcode == I_SET) i = !i;
Marko Mikulicic 0:c0ecb8bf28eb 27945 if (i) break;
Marko Mikulicic 0:c0ecb8bf28eb 27946 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27947
Marko Mikulicic 0:c0ecb8bf28eb 27948 case I_SPLIT:
Marko Mikulicic 0:c0ecb8bf28eb 27949 tmp_thr = curr_thread;
Marko Mikulicic 0:c0ecb8bf28eb 27950 curr_thread =
Marko Mikulicic 0:c0ecb8bf28eb 27951 re_newthread(curr_thread, pc->par.xy.y.y, current, &sub);
Marko Mikulicic 0:c0ecb8bf28eb 27952 if (curr_thread == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 27953 fprintf(stderr, "re_match: no memory for thread!\n");
Marko Mikulicic 0:c0ecb8bf28eb 27954 free_threads(tmp_thr);
Marko Mikulicic 0:c0ecb8bf28eb 27955 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27956 }
Marko Mikulicic 0:c0ecb8bf28eb 27957 pc = pc->par.xy.x;
Marko Mikulicic 0:c0ecb8bf28eb 27958 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27959
Marko Mikulicic 0:c0ecb8bf28eb 27960 case I_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27961 case I_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27962 i = (current > bol && iswordchar(current[-1]));
Marko Mikulicic 0:c0ecb8bf28eb 27963 if (iswordchar(current[0])) i = !i;
Marko Mikulicic 0:c0ecb8bf28eb 27964 if (pc->opcode == I_WORD_N) i = !i;
Marko Mikulicic 0:c0ecb8bf28eb 27965 if (i) break;
Marko Mikulicic 0:c0ecb8bf28eb 27966 /* goto no_match; */
Marko Mikulicic 0:c0ecb8bf28eb 27967
Marko Mikulicic 0:c0ecb8bf28eb 27968 default:
Marko Mikulicic 0:c0ecb8bf28eb 27969 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27970 }
Marko Mikulicic 0:c0ecb8bf28eb 27971 pc++;
Marko Mikulicic 0:c0ecb8bf28eb 27972 }
Marko Mikulicic 0:c0ecb8bf28eb 27973 no_match:
Marko Mikulicic 0:c0ecb8bf28eb 27974 ;
Marko Mikulicic 0:c0ecb8bf28eb 27975 } while (curr_thread->prev != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 27976 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27977 }
Marko Mikulicic 0:c0ecb8bf28eb 27978
Marko Mikulicic 0:c0ecb8bf28eb 27979 int slre_exec(struct slre_prog *prog, int flag_g, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 27980 const char *end, struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 27981 struct slre_loot tmpsub;
Marko Mikulicic 0:c0ecb8bf28eb 27982 const char *st = start;
Marko Mikulicic 0:c0ecb8bf28eb 27983
Marko Mikulicic 0:c0ecb8bf28eb 27984 if (!loot) loot = &tmpsub;
Marko Mikulicic 0:c0ecb8bf28eb 27985 memset(loot, 0, sizeof(*loot));
Marko Mikulicic 0:c0ecb8bf28eb 27986
Marko Mikulicic 0:c0ecb8bf28eb 27987 if (!flag_g) {
Marko Mikulicic 0:c0ecb8bf28eb 27988 loot->num_captures = prog->num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 27989 return !re_match(prog->start, start, end, start, prog->flags, loot);
Marko Mikulicic 0:c0ecb8bf28eb 27990 }
Marko Mikulicic 0:c0ecb8bf28eb 27991
Marko Mikulicic 0:c0ecb8bf28eb 27992 while (re_match(prog->start, st, end, start, prog->flags, &tmpsub)) {
Marko Mikulicic 0:c0ecb8bf28eb 27993 unsigned int i;
Marko Mikulicic 0:c0ecb8bf28eb 27994 st = tmpsub.caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 27995 for (i = 0; i < prog->num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 27996 struct slre_cap *l = &loot->caps[loot->num_captures + i];
Marko Mikulicic 0:c0ecb8bf28eb 27997 struct slre_cap *s = &tmpsub.caps[i];
Marko Mikulicic 0:c0ecb8bf28eb 27998 l->start = s->start;
Marko Mikulicic 0:c0ecb8bf28eb 27999 l->end = s->end;
Marko Mikulicic 0:c0ecb8bf28eb 28000 }
Marko Mikulicic 0:c0ecb8bf28eb 28001 loot->num_captures += prog->num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 28002 }
Marko Mikulicic 0:c0ecb8bf28eb 28003 return !loot->num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 28004 }
Marko Mikulicic 0:c0ecb8bf28eb 28005
Marko Mikulicic 0:c0ecb8bf28eb 28006 int slre_replace(struct slre_loot *loot, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 28007 const char *rstr, size_t rstr_len, struct slre_loot *dstsub) {
Marko Mikulicic 0:c0ecb8bf28eb 28008 int size = 0, n;
Marko Mikulicic 0:c0ecb8bf28eb 28009 Rune curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 28010 const char *const rstr_end = rstr + rstr_len;
Marko Mikulicic 0:c0ecb8bf28eb 28011
Marko Mikulicic 0:c0ecb8bf28eb 28012 memset(dstsub, 0, sizeof(*dstsub));
Marko Mikulicic 0:c0ecb8bf28eb 28013 while (rstr < rstr_end && !(n = re_nextc_raw(&curr_rune, &rstr, rstr_end)) &&
Marko Mikulicic 0:c0ecb8bf28eb 28014 curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 28015 int sz;
Marko Mikulicic 0:c0ecb8bf28eb 28016 if (n < 0) return n;
Marko Mikulicic 0:c0ecb8bf28eb 28017 if (curr_rune == '$') {
Marko Mikulicic 0:c0ecb8bf28eb 28018 n = re_nextc(&curr_rune, &rstr, rstr_end);
Marko Mikulicic 0:c0ecb8bf28eb 28019 if (n < 0) return n;
Marko Mikulicic 0:c0ecb8bf28eb 28020 switch (curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 28021 case '&':
Marko Mikulicic 0:c0ecb8bf28eb 28022 sz = loot->caps[0].end - loot->caps[0].start;
Marko Mikulicic 0:c0ecb8bf28eb 28023 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 28024 dstsub->caps[dstsub->num_captures++] = loot->caps[0];
Marko Mikulicic 0:c0ecb8bf28eb 28025 break;
Marko Mikulicic 0:c0ecb8bf28eb 28026 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 28027 case '1':
Marko Mikulicic 0:c0ecb8bf28eb 28028 case '2':
Marko Mikulicic 0:c0ecb8bf28eb 28029 case '3':
Marko Mikulicic 0:c0ecb8bf28eb 28030 case '4':
Marko Mikulicic 0:c0ecb8bf28eb 28031 case '5':
Marko Mikulicic 0:c0ecb8bf28eb 28032 case '6':
Marko Mikulicic 0:c0ecb8bf28eb 28033 case '7':
Marko Mikulicic 0:c0ecb8bf28eb 28034 case '8':
Marko Mikulicic 0:c0ecb8bf28eb 28035 case '9': {
Marko Mikulicic 0:c0ecb8bf28eb 28036 int sbn = dec(curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 28037 if (0 == sbn && rstr[0] && isdigitrune(rstr[0])) {
Marko Mikulicic 0:c0ecb8bf28eb 28038 n = re_nextc(&curr_rune, &rstr, rstr_end);
Marko Mikulicic 0:c0ecb8bf28eb 28039 if (n < 0) return n;
Marko Mikulicic 0:c0ecb8bf28eb 28040 sz = dec(curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 28041 sbn = sbn * 10 + sz;
Marko Mikulicic 0:c0ecb8bf28eb 28042 }
Marko Mikulicic 0:c0ecb8bf28eb 28043 if (sbn >= loot->num_captures) break;
Marko Mikulicic 0:c0ecb8bf28eb 28044 sz = loot->caps[sbn].end - loot->caps[sbn].start;
Marko Mikulicic 0:c0ecb8bf28eb 28045 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 28046 dstsub->caps[dstsub->num_captures++] = loot->caps[sbn];
Marko Mikulicic 0:c0ecb8bf28eb 28047 break;
Marko Mikulicic 0:c0ecb8bf28eb 28048 }
Marko Mikulicic 0:c0ecb8bf28eb 28049 case '`':
Marko Mikulicic 0:c0ecb8bf28eb 28050 sz = loot->caps[0].start - src;
Marko Mikulicic 0:c0ecb8bf28eb 28051 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 28052 dstsub->caps[dstsub->num_captures].start = src;
Marko Mikulicic 0:c0ecb8bf28eb 28053 dstsub->caps[dstsub->num_captures++].end = loot->caps[0].start;
Marko Mikulicic 0:c0ecb8bf28eb 28054 break;
Marko Mikulicic 0:c0ecb8bf28eb 28055 case '\'':
Marko Mikulicic 0:c0ecb8bf28eb 28056 sz = src + src_len - loot->caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 28057 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 28058 dstsub->caps[dstsub->num_captures].start = loot->caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 28059 dstsub->caps[dstsub->num_captures++].end = loot->caps[0].end + sz;
Marko Mikulicic 0:c0ecb8bf28eb 28060 break;
Marko Mikulicic 0:c0ecb8bf28eb 28061 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 28062 size++;
Marko Mikulicic 0:c0ecb8bf28eb 28063 dstsub->caps[dstsub->num_captures].start = rstr - 1;
Marko Mikulicic 0:c0ecb8bf28eb 28064 dstsub->caps[dstsub->num_captures++].end = rstr;
Marko Mikulicic 0:c0ecb8bf28eb 28065 break;
Marko Mikulicic 0:c0ecb8bf28eb 28066 default:
Marko Mikulicic 0:c0ecb8bf28eb 28067 return SLRE_BAD_CHAR_AFTER_USD;
Marko Mikulicic 0:c0ecb8bf28eb 28068 }
Marko Mikulicic 0:c0ecb8bf28eb 28069 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28070 char tmps[300], *d = tmps;
Marko Mikulicic 0:c0ecb8bf28eb 28071 size += (sz = runetochar(d, &curr_rune));
Marko Mikulicic 0:c0ecb8bf28eb 28072 if (!dstsub->num_captures ||
Marko Mikulicic 0:c0ecb8bf28eb 28073 dstsub->caps[dstsub->num_captures - 1].end != rstr - sz) {
Marko Mikulicic 0:c0ecb8bf28eb 28074 dstsub->caps[dstsub->num_captures].start = rstr - sz;
Marko Mikulicic 0:c0ecb8bf28eb 28075 dstsub->caps[dstsub->num_captures++].end = rstr;
Marko Mikulicic 0:c0ecb8bf28eb 28076 } else
Marko Mikulicic 0:c0ecb8bf28eb 28077 dstsub->caps[dstsub->num_captures - 1].end = rstr;
Marko Mikulicic 0:c0ecb8bf28eb 28078 }
Marko Mikulicic 0:c0ecb8bf28eb 28079 }
Marko Mikulicic 0:c0ecb8bf28eb 28080 return size;
Marko Mikulicic 0:c0ecb8bf28eb 28081 }
Marko Mikulicic 0:c0ecb8bf28eb 28082
Marko Mikulicic 0:c0ecb8bf28eb 28083 int slre_match(const char *re, size_t re_len, const char *flags, size_t fl_len,
Marko Mikulicic 0:c0ecb8bf28eb 28084 const char *str, size_t str_len, struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 28085 struct slre_prog *prog = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28086 int res;
Marko Mikulicic 0:c0ecb8bf28eb 28087
Marko Mikulicic 0:c0ecb8bf28eb 28088 if ((res = slre_compile(re, re_len, flags, fl_len, &prog, 1)) == SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28089 res = slre_exec(prog, prog->flags & SLRE_FLAG_G, str, str + str_len, loot);
Marko Mikulicic 0:c0ecb8bf28eb 28090 slre_free(prog);
Marko Mikulicic 0:c0ecb8bf28eb 28091 }
Marko Mikulicic 0:c0ecb8bf28eb 28092
Marko Mikulicic 0:c0ecb8bf28eb 28093 return res;
Marko Mikulicic 0:c0ecb8bf28eb 28094 }
Marko Mikulicic 0:c0ecb8bf28eb 28095
Marko Mikulicic 0:c0ecb8bf28eb 28096 int slre_get_flags(struct slre_prog *crp) {
Marko Mikulicic 0:c0ecb8bf28eb 28097 return crp->flags;
Marko Mikulicic 0:c0ecb8bf28eb 28098 }
Marko Mikulicic 0:c0ecb8bf28eb 28099
Marko Mikulicic 0:c0ecb8bf28eb 28100 #ifdef SLRE_TEST
Marko Mikulicic 0:c0ecb8bf28eb 28101
Marko Mikulicic 0:c0ecb8bf28eb 28102 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 28103
Marko Mikulicic 0:c0ecb8bf28eb 28104 static const char *err_code_to_str(int err_code) {
Marko Mikulicic 0:c0ecb8bf28eb 28105 static const char *ar[] = {
Marko Mikulicic 0:c0ecb8bf28eb 28106 "no error", "invalid decimal digit", "invalid hex digit",
Marko Mikulicic 0:c0ecb8bf28eb 28107 "invalid escape character", "invalid unterminated escape sequence",
Marko Mikulicic 0:c0ecb8bf28eb 28108 "syntax error", "unmatched left parenthesis",
Marko Mikulicic 0:c0ecb8bf28eb 28109 "unmatched right parenthesis", "numeric overflow",
Marko Mikulicic 0:c0ecb8bf28eb 28110 "infinite loop empty string", "too many charsets",
Marko Mikulicic 0:c0ecb8bf28eb 28111 "invalid charset range", "charset is too large", "malformed charset",
Marko Mikulicic 0:c0ecb8bf28eb 28112 "invalid back reference", "too many captures", "invalid quantifier",
Marko Mikulicic 0:c0ecb8bf28eb 28113 "bad character after $"};
Marko Mikulicic 0:c0ecb8bf28eb 28114
Marko Mikulicic 0:c0ecb8bf28eb 28115 typedef char static_assertion_err_codes_out_of_sync
Marko Mikulicic 0:c0ecb8bf28eb 28116 [2 * !!(((sizeof(ar) / sizeof(ar[0])) == SLRE_BAD_CHAR_AFTER_USD + 1)) -
Marko Mikulicic 0:c0ecb8bf28eb 28117 1];
Marko Mikulicic 0:c0ecb8bf28eb 28118
Marko Mikulicic 0:c0ecb8bf28eb 28119 return err_code >= 0 && err_code < (int) (sizeof(ar) / sizeof(ar[0]))
Marko Mikulicic 0:c0ecb8bf28eb 28120 ? ar[err_code]
Marko Mikulicic 0:c0ecb8bf28eb 28121 : "invalid error code";
Marko Mikulicic 0:c0ecb8bf28eb 28122 }
Marko Mikulicic 0:c0ecb8bf28eb 28123
Marko Mikulicic 0:c0ecb8bf28eb 28124 #define RE_TEST_STR_SIZE 2000
Marko Mikulicic 0:c0ecb8bf28eb 28125
Marko Mikulicic 0:c0ecb8bf28eb 28126 static unsigned get_flags(const char *ch) {
Marko Mikulicic 0:c0ecb8bf28eb 28127 unsigned int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28128
Marko Mikulicic 0:c0ecb8bf28eb 28129 while (*ch != '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 28130 switch (*ch) {
Marko Mikulicic 0:c0ecb8bf28eb 28131 case 'g':
Marko Mikulicic 0:c0ecb8bf28eb 28132 flags |= SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 28133 break;
Marko Mikulicic 0:c0ecb8bf28eb 28134 case 'i':
Marko Mikulicic 0:c0ecb8bf28eb 28135 flags |= SLRE_FLAG_I;
Marko Mikulicic 0:c0ecb8bf28eb 28136 break;
Marko Mikulicic 0:c0ecb8bf28eb 28137 case 'm':
Marko Mikulicic 0:c0ecb8bf28eb 28138 flags |= SLRE_FLAG_M;
Marko Mikulicic 0:c0ecb8bf28eb 28139 break;
Marko Mikulicic 0:c0ecb8bf28eb 28140 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 28141 flags |= SLRE_FLAG_RE;
Marko Mikulicic 0:c0ecb8bf28eb 28142 break;
Marko Mikulicic 0:c0ecb8bf28eb 28143 default:
Marko Mikulicic 0:c0ecb8bf28eb 28144 return flags;
Marko Mikulicic 0:c0ecb8bf28eb 28145 }
Marko Mikulicic 0:c0ecb8bf28eb 28146 ch++;
Marko Mikulicic 0:c0ecb8bf28eb 28147 }
Marko Mikulicic 0:c0ecb8bf28eb 28148 return flags;
Marko Mikulicic 0:c0ecb8bf28eb 28149 }
Marko Mikulicic 0:c0ecb8bf28eb 28150
Marko Mikulicic 0:c0ecb8bf28eb 28151 static void show_usage_and_exit(char *argv[]) {
Marko Mikulicic 0:c0ecb8bf28eb 28152 fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]);
Marko Mikulicic 0:c0ecb8bf28eb 28153 fprintf(stderr, "%s\n", "OPTIONS:");
Marko Mikulicic 0:c0ecb8bf28eb 28154 fprintf(stderr, "%s\n", " -p <regex_pattern> Regex pattern");
Marko Mikulicic 0:c0ecb8bf28eb 28155 fprintf(stderr, "%s\n", " -o <regex_flags> Combination of g,i,m");
Marko Mikulicic 0:c0ecb8bf28eb 28156 fprintf(stderr, "%s\n", " -s <string> String to match");
Marko Mikulicic 0:c0ecb8bf28eb 28157 fprintf(stderr, "%s\n", " -f <file_name> Match lines from file");
Marko Mikulicic 0:c0ecb8bf28eb 28158 fprintf(stderr, "%s\n", " -n <cap_no> Show given capture");
Marko Mikulicic 0:c0ecb8bf28eb 28159 fprintf(stderr, "%s\n", " -r <replace_str> Replace given capture");
Marko Mikulicic 0:c0ecb8bf28eb 28160 fprintf(stderr, "%s\n", " -v Show verbose stats");
Marko Mikulicic 0:c0ecb8bf28eb 28161 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28162 }
Marko Mikulicic 0:c0ecb8bf28eb 28163
Marko Mikulicic 0:c0ecb8bf28eb 28164 static int process_line(struct slre_prog *pr, const char *flags,
Marko Mikulicic 0:c0ecb8bf28eb 28165 const char *line, const char *cap_no,
Marko Mikulicic 0:c0ecb8bf28eb 28166 const char *replace, const char *verbose) {
Marko Mikulicic 0:c0ecb8bf28eb 28167 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 28168 unsigned int fl = flags == NULL ? 0 : get_flags(flags);
Marko Mikulicic 0:c0ecb8bf28eb 28169 int i, n = cap_no == NULL ? -1 : atoi(cap_no), err_code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28170 struct slre_cap *cap = &loot.caps[n];
Marko Mikulicic 0:c0ecb8bf28eb 28171
Marko Mikulicic 0:c0ecb8bf28eb 28172 err_code =
Marko Mikulicic 0:c0ecb8bf28eb 28173 slre_exec(pr, pr->flags & SLRE_FLAG_G, line, line + strlen(line), &loot);
Marko Mikulicic 0:c0ecb8bf28eb 28174 if (err_code == SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28175 if (n >= 0 && n < loot.num_captures && replace != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28176 struct slre_cap *cap = &loot.caps[n];
Marko Mikulicic 0:c0ecb8bf28eb 28177 printf("%.*s", (int) (cap->start - line), line);
Marko Mikulicic 0:c0ecb8bf28eb 28178 printf("%s", replace);
Marko Mikulicic 0:c0ecb8bf28eb 28179 printf("%.*s", (int) ((line + strlen(line)) - cap->end), cap->end);
Marko Mikulicic 0:c0ecb8bf28eb 28180 } else if (n >= 0 && n < loot.num_captures) {
Marko Mikulicic 0:c0ecb8bf28eb 28181 printf("%.*s\n", (int) (cap->end - cap->start), cap->start);
Marko Mikulicic 0:c0ecb8bf28eb 28182 }
Marko Mikulicic 0:c0ecb8bf28eb 28183
Marko Mikulicic 0:c0ecb8bf28eb 28184 if (verbose != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28185 fprintf(stderr, "%s\n", "Captures:");
Marko Mikulicic 0:c0ecb8bf28eb 28186 for (i = 0; i < loot.num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 28187 fprintf(stderr, "%d [%.*s]\n", i,
Marko Mikulicic 0:c0ecb8bf28eb 28188 (int) (loot.caps[i].end - loot.caps[i].start),
Marko Mikulicic 0:c0ecb8bf28eb 28189 loot.caps[i].start);
Marko Mikulicic 0:c0ecb8bf28eb 28190 }
Marko Mikulicic 0:c0ecb8bf28eb 28191 }
Marko Mikulicic 0:c0ecb8bf28eb 28192 }
Marko Mikulicic 0:c0ecb8bf28eb 28193
Marko Mikulicic 0:c0ecb8bf28eb 28194 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 28195 }
Marko Mikulicic 0:c0ecb8bf28eb 28196
Marko Mikulicic 0:c0ecb8bf28eb 28197 int main(int argc, char **argv) {
Marko Mikulicic 0:c0ecb8bf28eb 28198 const char *str = NULL, *pattern = NULL, *replace = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28199 const char *flags = "", *file_name = NULL, *cap_no = NULL, *verbose = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28200 struct slre_prog *pr = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28201 int i, err_code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28202
Marko Mikulicic 0:c0ecb8bf28eb 28203 /* Execute inline code */
Marko Mikulicic 0:c0ecb8bf28eb 28204 for (i = 1; i < argc; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 28205 if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28206 pattern = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28207 } else if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28208 flags = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28209 } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28210 str = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28211 } else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28212 file_name = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28213 } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28214 cap_no = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28215 } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28216 replace = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28217 } else if (strcmp(argv[i], "-v") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28218 verbose = "";
Marko Mikulicic 0:c0ecb8bf28eb 28219 } else if (strcmp(argv[i], "-h") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28220 show_usage_and_exit(argv);
Marko Mikulicic 0:c0ecb8bf28eb 28221 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28222 show_usage_and_exit(argv);
Marko Mikulicic 0:c0ecb8bf28eb 28223 }
Marko Mikulicic 0:c0ecb8bf28eb 28224 }
Marko Mikulicic 0:c0ecb8bf28eb 28225
Marko Mikulicic 0:c0ecb8bf28eb 28226 if (pattern == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28227 fprintf(stderr, "%s\n", "-p option is mandatory");
Marko Mikulicic 0:c0ecb8bf28eb 28228 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28229 } else if ((err_code = slre_compile(pattern, strlen(pattern), flags,
Marko Mikulicic 0:c0ecb8bf28eb 28230 strlen(flags), &pr, 1)) != SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28231 fprintf(stderr, "slre_compile(%s): %s\n", argv[0],
Marko Mikulicic 0:c0ecb8bf28eb 28232 err_code_to_str(err_code));
Marko Mikulicic 0:c0ecb8bf28eb 28233 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28234 } else if (str != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28235 err_code = process_line(pr, flags, str, cap_no, replace, verbose);
Marko Mikulicic 0:c0ecb8bf28eb 28236 } else if (file_name != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28237 FILE *fp = strcmp(file_name, "-") == 0 ? stdin : fopen(file_name, "rb");
Marko Mikulicic 0:c0ecb8bf28eb 28238 char line[20 * 1024];
Marko Mikulicic 0:c0ecb8bf28eb 28239 if (fp == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28240 fprintf(stderr, "Cannot open %s: %s\n", file_name, strerror(errno));
Marko Mikulicic 0:c0ecb8bf28eb 28241 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28242 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28243 /* Return success if at least one line matches */
Marko Mikulicic 0:c0ecb8bf28eb 28244 err_code = 1;
Marko Mikulicic 0:c0ecb8bf28eb 28245 while (fgets(line, sizeof(line), fp) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28246 if (process_line(pr, flags, line, cap_no, replace, verbose) ==
Marko Mikulicic 0:c0ecb8bf28eb 28247 SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28248 err_code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28249 }
Marko Mikulicic 0:c0ecb8bf28eb 28250 }
Marko Mikulicic 0:c0ecb8bf28eb 28251 fclose(fp); /* If fp == stdin, it is safe to close, too */
Marko Mikulicic 0:c0ecb8bf28eb 28252 }
Marko Mikulicic 0:c0ecb8bf28eb 28253 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28254 fprintf(stderr, "%s\n", "Please specify one of -s or -f options");
Marko Mikulicic 0:c0ecb8bf28eb 28255 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28256 }
Marko Mikulicic 0:c0ecb8bf28eb 28257 slre_free(pr);
Marko Mikulicic 0:c0ecb8bf28eb 28258
Marko Mikulicic 0:c0ecb8bf28eb 28259 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 28260 }
Marko Mikulicic 0:c0ecb8bf28eb 28261 #endif /* SLRE_TEST */
Marko Mikulicic 0:c0ecb8bf28eb 28262
Marko Mikulicic 0:c0ecb8bf28eb 28263 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 28264 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 28265 #line 1 "v7/src/heapusage.c"
Marko Mikulicic 0:c0ecb8bf28eb 28266 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28267 /*
Marko Mikulicic 0:c0ecb8bf28eb 28268 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 28269 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 28270 */
Marko Mikulicic 0:c0ecb8bf28eb 28271
Marko Mikulicic 0:c0ecb8bf28eb 28272 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 28273 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 28274 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 28275
Marko Mikulicic 0:c0ecb8bf28eb 28276 #if defined(V7_HEAPUSAGE_ENABLE)
Marko Mikulicic 0:c0ecb8bf28eb 28277
Marko Mikulicic 0:c0ecb8bf28eb 28278 /*
Marko Mikulicic 0:c0ecb8bf28eb 28279 * A flag that is set by GC before allocating its buffers, so we can
Marko Mikulicic 0:c0ecb8bf28eb 28280 * distinguish these buffers from other allocations
Marko Mikulicic 0:c0ecb8bf28eb 28281 */
Marko Mikulicic 0:c0ecb8bf28eb 28282 volatile int heap_dont_count = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28283
Marko Mikulicic 0:c0ecb8bf28eb 28284 extern void *__real_malloc(size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 28285 extern void *__real_calloc(size_t num, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 28286 extern void *__real_realloc(void *p, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 28287 extern void __real_free(void *p);
Marko Mikulicic 0:c0ecb8bf28eb 28288
Marko Mikulicic 0:c0ecb8bf28eb 28289 /* TODO(dfrank): make it dynamically allocated from heap */
Marko Mikulicic 0:c0ecb8bf28eb 28290 #define CELLS_CNT (1024 * 32)
Marko Mikulicic 0:c0ecb8bf28eb 28291
Marko Mikulicic 0:c0ecb8bf28eb 28292 typedef struct cell {
Marko Mikulicic 0:c0ecb8bf28eb 28293 void *p;
Marko Mikulicic 0:c0ecb8bf28eb 28294 unsigned dont_count : 1;
Marko Mikulicic 0:c0ecb8bf28eb 28295 unsigned size : 31;
Marko Mikulicic 0:c0ecb8bf28eb 28296 } cell_t;
Marko Mikulicic 0:c0ecb8bf28eb 28297
Marko Mikulicic 0:c0ecb8bf28eb 28298 typedef struct alloc_registry {
Marko Mikulicic 0:c0ecb8bf28eb 28299 size_t used_cells_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28300 size_t allocated_size;
Marko Mikulicic 0:c0ecb8bf28eb 28301 size_t real_used_cells_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28302 size_t real_allocated_size;
Marko Mikulicic 0:c0ecb8bf28eb 28303 cell_t cells[CELLS_CNT];
Marko Mikulicic 0:c0ecb8bf28eb 28304 } alloc_registry_t;
Marko Mikulicic 0:c0ecb8bf28eb 28305
Marko Mikulicic 0:c0ecb8bf28eb 28306 static alloc_registry_t registry = {0};
Marko Mikulicic 0:c0ecb8bf28eb 28307
Marko Mikulicic 0:c0ecb8bf28eb 28308 /*
Marko Mikulicic 0:c0ecb8bf28eb 28309 * Make a record about an allocated buffer `p` of size `size`
Marko Mikulicic 0:c0ecb8bf28eb 28310 */
Marko Mikulicic 0:c0ecb8bf28eb 28311 static void cell_allocated(void *p, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28312 int i;
Marko Mikulicic 0:c0ecb8bf28eb 28313 int cell_num = -1;
Marko Mikulicic 0:c0ecb8bf28eb 28314
Marko Mikulicic 0:c0ecb8bf28eb 28315 if (p != NULL && size != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28316 /* TODO(dfrank): make it dynamically allocated from heap */
Marko Mikulicic 0:c0ecb8bf28eb 28317 assert(registry.real_used_cells_cnt < CELLS_CNT);
Marko Mikulicic 0:c0ecb8bf28eb 28318
Marko Mikulicic 0:c0ecb8bf28eb 28319 for (i = 0; i < CELLS_CNT; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 28320 if (registry.cells[i].p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28321 cell_num = i;
Marko Mikulicic 0:c0ecb8bf28eb 28322 break;
Marko Mikulicic 0:c0ecb8bf28eb 28323 }
Marko Mikulicic 0:c0ecb8bf28eb 28324 }
Marko Mikulicic 0:c0ecb8bf28eb 28325
Marko Mikulicic 0:c0ecb8bf28eb 28326 assert(cell_num != -1);
Marko Mikulicic 0:c0ecb8bf28eb 28327
Marko Mikulicic 0:c0ecb8bf28eb 28328 registry.cells[cell_num].p = p;
Marko Mikulicic 0:c0ecb8bf28eb 28329 registry.cells[cell_num].size = size;
Marko Mikulicic 0:c0ecb8bf28eb 28330 registry.cells[cell_num].dont_count = !!heap_dont_count;
Marko Mikulicic 0:c0ecb8bf28eb 28331
Marko Mikulicic 0:c0ecb8bf28eb 28332 registry.real_allocated_size += size;
Marko Mikulicic 0:c0ecb8bf28eb 28333 registry.real_used_cells_cnt += 1;
Marko Mikulicic 0:c0ecb8bf28eb 28334
Marko Mikulicic 0:c0ecb8bf28eb 28335 if (!heap_dont_count) {
Marko Mikulicic 0:c0ecb8bf28eb 28336 registry.allocated_size += size;
Marko Mikulicic 0:c0ecb8bf28eb 28337 registry.used_cells_cnt += 1;
Marko Mikulicic 0:c0ecb8bf28eb 28338 }
Marko Mikulicic 0:c0ecb8bf28eb 28339
Marko Mikulicic 0:c0ecb8bf28eb 28340 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 28341 printf("alloc=0x%lx, size=%lu, total=%lu\n", (unsigned long)p, size,
Marko Mikulicic 0:c0ecb8bf28eb 28342 registry.allocated_size);
Marko Mikulicic 0:c0ecb8bf28eb 28343 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28344 }
Marko Mikulicic 0:c0ecb8bf28eb 28345 }
Marko Mikulicic 0:c0ecb8bf28eb 28346
Marko Mikulicic 0:c0ecb8bf28eb 28347 /*
Marko Mikulicic 0:c0ecb8bf28eb 28348 * Delete a record about an allocated buffer `p`. If our registry does not
Marko Mikulicic 0:c0ecb8bf28eb 28349 * contain anything about the given pointer, the call is ignored. We can't
Marko Mikulicic 0:c0ecb8bf28eb 28350 * generate an error because shared libraries still use unwrapped heap
Marko Mikulicic 0:c0ecb8bf28eb 28351 * functions, so we can face "unknown" pointers.
Marko Mikulicic 0:c0ecb8bf28eb 28352 */
Marko Mikulicic 0:c0ecb8bf28eb 28353 static void cell_freed(void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 28354 int i;
Marko Mikulicic 0:c0ecb8bf28eb 28355 int cell_num = -1;
Marko Mikulicic 0:c0ecb8bf28eb 28356
Marko Mikulicic 0:c0ecb8bf28eb 28357 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28358 assert(registry.real_used_cells_cnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 28359
Marko Mikulicic 0:c0ecb8bf28eb 28360 for (i = 0; i < CELLS_CNT; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 28361 if (registry.cells[i].p == p) {
Marko Mikulicic 0:c0ecb8bf28eb 28362 cell_num = i;
Marko Mikulicic 0:c0ecb8bf28eb 28363 break;
Marko Mikulicic 0:c0ecb8bf28eb 28364 }
Marko Mikulicic 0:c0ecb8bf28eb 28365 }
Marko Mikulicic 0:c0ecb8bf28eb 28366
Marko Mikulicic 0:c0ecb8bf28eb 28367 /*
Marko Mikulicic 0:c0ecb8bf28eb 28368 * NOTE: it would be nice to have `assert(cell_num != -1);`, but
Marko Mikulicic 0:c0ecb8bf28eb 28369 * unfortunately not all allocations are wrapped: shared libraries will
Marko Mikulicic 0:c0ecb8bf28eb 28370 * still use unwrapped mallocs, so we might get unknown pointers here.
Marko Mikulicic 0:c0ecb8bf28eb 28371 */
Marko Mikulicic 0:c0ecb8bf28eb 28372
Marko Mikulicic 0:c0ecb8bf28eb 28373 if (cell_num != -1) {
Marko Mikulicic 0:c0ecb8bf28eb 28374 registry.real_allocated_size -= registry.cells[cell_num].size;
Marko Mikulicic 0:c0ecb8bf28eb 28375 registry.real_used_cells_cnt -= 1;
Marko Mikulicic 0:c0ecb8bf28eb 28376
Marko Mikulicic 0:c0ecb8bf28eb 28377 if (!registry.cells[cell_num].dont_count) {
Marko Mikulicic 0:c0ecb8bf28eb 28378 registry.allocated_size -= registry.cells[cell_num].size;
Marko Mikulicic 0:c0ecb8bf28eb 28379 registry.used_cells_cnt -= 1;
Marko Mikulicic 0:c0ecb8bf28eb 28380 }
Marko Mikulicic 0:c0ecb8bf28eb 28381
Marko Mikulicic 0:c0ecb8bf28eb 28382 registry.cells[cell_num].p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28383 registry.cells[cell_num].size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28384 registry.cells[cell_num].dont_count = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28385
Marko Mikulicic 0:c0ecb8bf28eb 28386 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 28387 printf("free=0x%lx, total=%lu\n", (unsigned long)p, registry.allocated_size);
Marko Mikulicic 0:c0ecb8bf28eb 28388 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28389 }
Marko Mikulicic 0:c0ecb8bf28eb 28390 }
Marko Mikulicic 0:c0ecb8bf28eb 28391 }
Marko Mikulicic 0:c0ecb8bf28eb 28392
Marko Mikulicic 0:c0ecb8bf28eb 28393 /*
Marko Mikulicic 0:c0ecb8bf28eb 28394 * Wrappers of the standard heap functions
Marko Mikulicic 0:c0ecb8bf28eb 28395 */
Marko Mikulicic 0:c0ecb8bf28eb 28396
Marko Mikulicic 0:c0ecb8bf28eb 28397 void *__wrap_malloc(size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28398 void *ret = __real_malloc(size);
Marko Mikulicic 0:c0ecb8bf28eb 28399 cell_allocated(ret, size);
Marko Mikulicic 0:c0ecb8bf28eb 28400 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 28401 }
Marko Mikulicic 0:c0ecb8bf28eb 28402
Marko Mikulicic 0:c0ecb8bf28eb 28403 void *__wrap_calloc(size_t num, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28404 void *ret = __real_calloc(num, size);
Marko Mikulicic 0:c0ecb8bf28eb 28405 cell_allocated(ret, num * size);
Marko Mikulicic 0:c0ecb8bf28eb 28406 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 28407 }
Marko Mikulicic 0:c0ecb8bf28eb 28408
Marko Mikulicic 0:c0ecb8bf28eb 28409 void *__wrap_realloc(void *p, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28410 void *ret;
Marko Mikulicic 0:c0ecb8bf28eb 28411 cell_freed(p);
Marko Mikulicic 0:c0ecb8bf28eb 28412 ret = __real_realloc(p, size);
Marko Mikulicic 0:c0ecb8bf28eb 28413 cell_allocated(ret, size);
Marko Mikulicic 0:c0ecb8bf28eb 28414 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 28415 }
Marko Mikulicic 0:c0ecb8bf28eb 28416
Marko Mikulicic 0:c0ecb8bf28eb 28417 void __wrap_free(void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 28418 __real_free(p);
Marko Mikulicic 0:c0ecb8bf28eb 28419 cell_freed(p);
Marko Mikulicic 0:c0ecb8bf28eb 28420 }
Marko Mikulicic 0:c0ecb8bf28eb 28421
Marko Mikulicic 0:c0ecb8bf28eb 28422 /*
Marko Mikulicic 0:c0ecb8bf28eb 28423 * Small API to get some stats, see header file for details
Marko Mikulicic 0:c0ecb8bf28eb 28424 */
Marko Mikulicic 0:c0ecb8bf28eb 28425
Marko Mikulicic 0:c0ecb8bf28eb 28426 size_t heapusage_alloc_size(void) {
Marko Mikulicic 0:c0ecb8bf28eb 28427 return registry.allocated_size;
Marko Mikulicic 0:c0ecb8bf28eb 28428 }
Marko Mikulicic 0:c0ecb8bf28eb 28429
Marko Mikulicic 0:c0ecb8bf28eb 28430 size_t heapusage_allocs_cnt(void) {
Marko Mikulicic 0:c0ecb8bf28eb 28431 return registry.used_cells_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28432 }
Marko Mikulicic 0:c0ecb8bf28eb 28433
Marko Mikulicic 0:c0ecb8bf28eb 28434 #endif /* V7_HEAPUSAGE_ENABLE */
Marko Mikulicic 0:c0ecb8bf28eb 28435 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 28436 #line 1 "v7/src/cyg_profile.c"
Marko Mikulicic 0:c0ecb8bf28eb 28437 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28438 /*
Marko Mikulicic 0:c0ecb8bf28eb 28439 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 28440 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 28441 */
Marko Mikulicic 0:c0ecb8bf28eb 28442
Marko Mikulicic 0:c0ecb8bf28eb 28443 /*
Marko Mikulicic 0:c0ecb8bf28eb 28444 * This file contains GCC/clang instrumentation callbacks. The actual
Marko Mikulicic 0:c0ecb8bf28eb 28445 * code in these callbacks depends on enabled features.
Marko Mikulicic 0:c0ecb8bf28eb 28446 *
Marko Mikulicic 0:c0ecb8bf28eb 28447 * Currently, the code from different subsystems is embedded right into
Marko Mikulicic 0:c0ecb8bf28eb 28448 * callbacks for performance reasons. It would be probably more elegant
Marko Mikulicic 0:c0ecb8bf28eb 28449 * to have subsystem-specific functions that will be called from these
Marko Mikulicic 0:c0ecb8bf28eb 28450 * callbacks, but since the callbacks are called really a lot (on each v7
Marko Mikulicic 0:c0ecb8bf28eb 28451 * function call), I decided it's better to inline the code right here.
Marko Mikulicic 0:c0ecb8bf28eb 28452 */
Marko Mikulicic 0:c0ecb8bf28eb 28453
Marko Mikulicic 0:c0ecb8bf28eb 28454 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28455 /* Amalgamated: #include "v7/src/cyg_profile.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28456 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28457
Marko Mikulicic 0:c0ecb8bf28eb 28458 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 28459
Marko Mikulicic 0:c0ecb8bf28eb 28460 #if defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 28461
Marko Mikulicic 0:c0ecb8bf28eb 28462 #define CALL_TRACE_SIZE 32
Marko Mikulicic 0:c0ecb8bf28eb 28463
Marko Mikulicic 0:c0ecb8bf28eb 28464 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 28465 uint16_t size;
Marko Mikulicic 0:c0ecb8bf28eb 28466 uint16_t missed_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28467 void *addresses[CALL_TRACE_SIZE];
Marko Mikulicic 0:c0ecb8bf28eb 28468 } call_trace_t;
Marko Mikulicic 0:c0ecb8bf28eb 28469
Marko Mikulicic 0:c0ecb8bf28eb 28470 static call_trace_t call_trace = {0};
Marko Mikulicic 0:c0ecb8bf28eb 28471
Marko Mikulicic 0:c0ecb8bf28eb 28472 NOINSTR
Marko Mikulicic 0:c0ecb8bf28eb 28473 void call_trace_print(const char *prefix, const char *suffix, size_t skip_cnt,
Marko Mikulicic 0:c0ecb8bf28eb 28474 size_t max_cnt) {
Marko Mikulicic 0:c0ecb8bf28eb 28475 int i;
Marko Mikulicic 0:c0ecb8bf28eb 28476 if (call_trace.missed_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28477 fprintf(stderr, "missed calls! (%d) ", (int) call_trace.missed_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 28478 }
Marko Mikulicic 0:c0ecb8bf28eb 28479 if (prefix != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28480 fprintf(stderr, "%s", prefix);
Marko Mikulicic 0:c0ecb8bf28eb 28481 }
Marko Mikulicic 0:c0ecb8bf28eb 28482 for (i = (int) call_trace.size - 1 - skip_cnt; i >= 0; i--) {
Marko Mikulicic 0:c0ecb8bf28eb 28483 fprintf(stderr, " %lx", (unsigned long) call_trace.addresses[i]);
Marko Mikulicic 0:c0ecb8bf28eb 28484 if (max_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28485 if (--max_cnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28486 break;
Marko Mikulicic 0:c0ecb8bf28eb 28487 }
Marko Mikulicic 0:c0ecb8bf28eb 28488 }
Marko Mikulicic 0:c0ecb8bf28eb 28489 }
Marko Mikulicic 0:c0ecb8bf28eb 28490 if (suffix != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28491 fprintf(stderr, "%s", suffix);
Marko Mikulicic 0:c0ecb8bf28eb 28492 }
Marko Mikulicic 0:c0ecb8bf28eb 28493 fprintf(stderr, "\n");
Marko Mikulicic 0:c0ecb8bf28eb 28494 }
Marko Mikulicic 0:c0ecb8bf28eb 28495
Marko Mikulicic 0:c0ecb8bf28eb 28496 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28497
Marko Mikulicic 0:c0ecb8bf28eb 28498 #ifndef IRAM
Marko Mikulicic 0:c0ecb8bf28eb 28499 #define IRAM
Marko Mikulicic 0:c0ecb8bf28eb 28500 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28501
Marko Mikulicic 0:c0ecb8bf28eb 28502 #ifndef NOINSTR
Marko Mikulicic 0:c0ecb8bf28eb 28503 #define NOINSTR __attribute__((no_instrument_function))
Marko Mikulicic 0:c0ecb8bf28eb 28504 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28505
Marko Mikulicic 0:c0ecb8bf28eb 28506 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 28507 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 28508 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 28509 IRAM NOINSTR void __cyg_profile_func_enter(void *this_fn, void *call_site);
Marko Mikulicic 0:c0ecb8bf28eb 28510
Marko Mikulicic 0:c0ecb8bf28eb 28511 IRAM NOINSTR void __cyg_profile_func_exit(void *this_fn, void *call_site);
Marko Mikulicic 0:c0ecb8bf28eb 28512
Marko Mikulicic 0:c0ecb8bf28eb 28513 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 28514 }
Marko Mikulicic 0:c0ecb8bf28eb 28515 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 28516
Marko Mikulicic 0:c0ecb8bf28eb 28517 IRAM void __cyg_profile_func_enter(void *this_fn, void *call_site) {
Marko Mikulicic 0:c0ecb8bf28eb 28518 #if defined(V7_STACK_GUARD_MIN_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 28519 {
Marko Mikulicic 0:c0ecb8bf28eb 28520 static int profile_enter = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28521 void *fp = __builtin_frame_address(0);
Marko Mikulicic 0:c0ecb8bf28eb 28522
Marko Mikulicic 0:c0ecb8bf28eb 28523 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28524
Marko Mikulicic 0:c0ecb8bf28eb 28525 if (profile_enter || v7_sp_limit == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 28526
Marko Mikulicic 0:c0ecb8bf28eb 28527 profile_enter++;
Marko Mikulicic 0:c0ecb8bf28eb 28528 if (v7_head != NULL && fp < v7_head->sp_lwm) v7_head->sp_lwm = fp;
Marko Mikulicic 0:c0ecb8bf28eb 28529
Marko Mikulicic 0:c0ecb8bf28eb 28530 if (((int) fp - (int) v7_sp_limit) < V7_STACK_GUARD_MIN_SIZE) {
Marko Mikulicic 0:c0ecb8bf28eb 28531 printf("fun %p sp %p limit %p left %d\n", this_fn, fp, v7_sp_limit,
Marko Mikulicic 0:c0ecb8bf28eb 28532 (int) fp - (int) v7_sp_limit);
Marko Mikulicic 0:c0ecb8bf28eb 28533 abort();
Marko Mikulicic 0:c0ecb8bf28eb 28534 }
Marko Mikulicic 0:c0ecb8bf28eb 28535 profile_enter--;
Marko Mikulicic 0:c0ecb8bf28eb 28536 }
Marko Mikulicic 0:c0ecb8bf28eb 28537 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28538
Marko Mikulicic 0:c0ecb8bf28eb 28539 #if defined(V7_ENABLE_GC_CHECK)
Marko Mikulicic 0:c0ecb8bf28eb 28540 {
Marko Mikulicic 0:c0ecb8bf28eb 28541 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28542 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28543 }
Marko Mikulicic 0:c0ecb8bf28eb 28544 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28545
Marko Mikulicic 0:c0ecb8bf28eb 28546 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 28547 {
Marko Mikulicic 0:c0ecb8bf28eb 28548 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 28549 struct stack_track_ctx *ctx;
Marko Mikulicic 0:c0ecb8bf28eb 28550 void *fp = __builtin_frame_address(1);
Marko Mikulicic 0:c0ecb8bf28eb 28551
Marko Mikulicic 0:c0ecb8bf28eb 28552 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28553 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28554
Marko Mikulicic 0:c0ecb8bf28eb 28555 /*
Marko Mikulicic 0:c0ecb8bf28eb 28556 * TODO(dfrank): it actually won't work for multiple instances of v7 running
Marko Mikulicic 0:c0ecb8bf28eb 28557 * in parallel threads. We need to know the exact v7 instance for which
Marko Mikulicic 0:c0ecb8bf28eb 28558 * current function is called, but so far I failed to find a way to do this.
Marko Mikulicic 0:c0ecb8bf28eb 28559 */
Marko Mikulicic 0:c0ecb8bf28eb 28560 for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) {
Marko Mikulicic 0:c0ecb8bf28eb 28561 for (ctx = v7->stack_track_ctx; ctx != NULL; ctx = ctx->next) {
Marko Mikulicic 0:c0ecb8bf28eb 28562 /* commented because it fails on legal code compiled with -O3 */
Marko Mikulicic 0:c0ecb8bf28eb 28563 /*assert(fp <= ctx->start);*/
Marko Mikulicic 0:c0ecb8bf28eb 28564
Marko Mikulicic 0:c0ecb8bf28eb 28565 if (fp < ctx->max) {
Marko Mikulicic 0:c0ecb8bf28eb 28566 ctx->max = fp;
Marko Mikulicic 0:c0ecb8bf28eb 28567 }
Marko Mikulicic 0:c0ecb8bf28eb 28568 }
Marko Mikulicic 0:c0ecb8bf28eb 28569 }
Marko Mikulicic 0:c0ecb8bf28eb 28570 }
Marko Mikulicic 0:c0ecb8bf28eb 28571 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28572
Marko Mikulicic 0:c0ecb8bf28eb 28573 #if defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 28574 if (call_trace.size < CALL_TRACE_SIZE) {
Marko Mikulicic 0:c0ecb8bf28eb 28575 call_trace.addresses[call_trace.size] = this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28576 call_trace.size++;
Marko Mikulicic 0:c0ecb8bf28eb 28577 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28578 call_trace.missed_cnt++;
Marko Mikulicic 0:c0ecb8bf28eb 28579 }
Marko Mikulicic 0:c0ecb8bf28eb 28580 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28581 }
Marko Mikulicic 0:c0ecb8bf28eb 28582
Marko Mikulicic 0:c0ecb8bf28eb 28583 IRAM void __cyg_profile_func_exit(void *this_fn, void *call_site) {
Marko Mikulicic 0:c0ecb8bf28eb 28584 #if defined(V7_STACK_GUARD_MIN_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 28585 {
Marko Mikulicic 0:c0ecb8bf28eb 28586 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28587 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28588 }
Marko Mikulicic 0:c0ecb8bf28eb 28589 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28590
Marko Mikulicic 0:c0ecb8bf28eb 28591 #if defined(V7_ENABLE_GC_CHECK)
Marko Mikulicic 0:c0ecb8bf28eb 28592 {
Marko Mikulicic 0:c0ecb8bf28eb 28593 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 28594 void *fp = __builtin_frame_address(1);
Marko Mikulicic 0:c0ecb8bf28eb 28595
Marko Mikulicic 0:c0ecb8bf28eb 28596 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28597 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28598
Marko Mikulicic 0:c0ecb8bf28eb 28599 for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) {
Marko Mikulicic 0:c0ecb8bf28eb 28600 v7_val_t **vp;
Marko Mikulicic 0:c0ecb8bf28eb 28601 if (v7->owned_values.buf == NULL) continue;
Marko Mikulicic 0:c0ecb8bf28eb 28602 vp = (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len -
Marko Mikulicic 0:c0ecb8bf28eb 28603 sizeof(v7_val_t *));
Marko Mikulicic 0:c0ecb8bf28eb 28604
Marko Mikulicic 0:c0ecb8bf28eb 28605 for (; (char *) vp >= v7->owned_values.buf; vp--) {
Marko Mikulicic 0:c0ecb8bf28eb 28606 /*
Marko Mikulicic 0:c0ecb8bf28eb 28607 * Check if a variable belongs to a dead stack frame.
Marko Mikulicic 0:c0ecb8bf28eb 28608 * Addresses lower than the parent frame belong to the
Marko Mikulicic 0:c0ecb8bf28eb 28609 * stack frame of the function about to return.
Marko Mikulicic 0:c0ecb8bf28eb 28610 * But the heap also usually below the stack and
Marko Mikulicic 0:c0ecb8bf28eb 28611 * we don't know the end of the stack. But this hook
Marko Mikulicic 0:c0ecb8bf28eb 28612 * is called at each function return, so we have
Marko Mikulicic 0:c0ecb8bf28eb 28613 * to check only up to the maximum stack frame size,
Marko Mikulicic 0:c0ecb8bf28eb 28614 * let's arbitrarily but reasonably set that at 8k.
Marko Mikulicic 0:c0ecb8bf28eb 28615 */
Marko Mikulicic 0:c0ecb8bf28eb 28616 if ((void *) *vp <= fp && (void *) *vp > (fp + 8196)) {
Marko Mikulicic 0:c0ecb8bf28eb 28617 fprintf(stderr, "Found owned variable after return\n");
Marko Mikulicic 0:c0ecb8bf28eb 28618 abort();
Marko Mikulicic 0:c0ecb8bf28eb 28619 }
Marko Mikulicic 0:c0ecb8bf28eb 28620 }
Marko Mikulicic 0:c0ecb8bf28eb 28621 }
Marko Mikulicic 0:c0ecb8bf28eb 28622 }
Marko Mikulicic 0:c0ecb8bf28eb 28623 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28624
Marko Mikulicic 0:c0ecb8bf28eb 28625 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 28626 {
Marko Mikulicic 0:c0ecb8bf28eb 28627 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28628 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28629 }
Marko Mikulicic 0:c0ecb8bf28eb 28630 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28631
Marko Mikulicic 0:c0ecb8bf28eb 28632 #if defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 28633 if (call_trace.missed_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28634 call_trace.missed_cnt--;
Marko Mikulicic 0:c0ecb8bf28eb 28635 } else if (call_trace.size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28636 if (call_trace.addresses[call_trace.size - 1] != this_fn) {
Marko Mikulicic 0:c0ecb8bf28eb 28637 abort();
Marko Mikulicic 0:c0ecb8bf28eb 28638 }
Marko Mikulicic 0:c0ecb8bf28eb 28639 call_trace.size--;
Marko Mikulicic 0:c0ecb8bf28eb 28640 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28641 /*
Marko Mikulicic 0:c0ecb8bf28eb 28642 * We may get here if calls to `__cyg_profile_func_exit()` and
Marko Mikulicic 0:c0ecb8bf28eb 28643 * `__cyg_profile_func_enter()` are unbalanced.
Marko Mikulicic 0:c0ecb8bf28eb 28644 *
Marko Mikulicic 0:c0ecb8bf28eb 28645 * TODO(dfrank) understand, why in the beginning of the program execution
Marko Mikulicic 0:c0ecb8bf28eb 28646 * we get here. I was sure this should be impossible.
Marko Mikulicic 0:c0ecb8bf28eb 28647 */
Marko Mikulicic 0:c0ecb8bf28eb 28648 /* abort(); */
Marko Mikulicic 0:c0ecb8bf28eb 28649 }
Marko Mikulicic 0:c0ecb8bf28eb 28650 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28651 }
Marko Mikulicic 0:c0ecb8bf28eb 28652
Marko Mikulicic 0:c0ecb8bf28eb 28653 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 28654
Marko Mikulicic 0:c0ecb8bf28eb 28655 void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 28656 /* insert new context at the head of the list */
Marko Mikulicic 0:c0ecb8bf28eb 28657 ctx->next = v7->stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 28658 v7->stack_track_ctx = ctx;
Marko Mikulicic 0:c0ecb8bf28eb 28659
Marko Mikulicic 0:c0ecb8bf28eb 28660 /* init both `max` and `start` to the current frame pointer */
Marko Mikulicic 0:c0ecb8bf28eb 28661 ctx->max = ctx->start = __builtin_frame_address(0);
Marko Mikulicic 0:c0ecb8bf28eb 28662 }
Marko Mikulicic 0:c0ecb8bf28eb 28663
Marko Mikulicic 0:c0ecb8bf28eb 28664 int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 28665 int diff;
Marko Mikulicic 0:c0ecb8bf28eb 28666
Marko Mikulicic 0:c0ecb8bf28eb 28667 /* this function can be called only for the head context */
Marko Mikulicic 0:c0ecb8bf28eb 28668 assert(v7->stack_track_ctx == ctx);
Marko Mikulicic 0:c0ecb8bf28eb 28669
Marko Mikulicic 0:c0ecb8bf28eb 28670 diff = (int) ((char *) ctx->start - (char *) ctx->max);
Marko Mikulicic 0:c0ecb8bf28eb 28671
Marko Mikulicic 0:c0ecb8bf28eb 28672 /* remove context from the linked list */
Marko Mikulicic 0:c0ecb8bf28eb 28673 v7->stack_track_ctx = ctx->next;
Marko Mikulicic 0:c0ecb8bf28eb 28674
Marko Mikulicic 0:c0ecb8bf28eb 28675 return (int) diff;
Marko Mikulicic 0:c0ecb8bf28eb 28676 }
Marko Mikulicic 0:c0ecb8bf28eb 28677
Marko Mikulicic 0:c0ecb8bf28eb 28678 #endif /* V7_ENABLE_STACK_TRACKING */
Marko Mikulicic 0:c0ecb8bf28eb 28679 #endif /* V7_CYG_PROFILE_ON */
Marko Mikulicic 0:c0ecb8bf28eb 28680 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 28681 #line 1 "v7/src/std_object.c"
Marko Mikulicic 0:c0ecb8bf28eb 28682 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28683 /*
Marko Mikulicic 0:c0ecb8bf28eb 28684 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 28685 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 28686 */
Marko Mikulicic 0:c0ecb8bf28eb 28687
Marko Mikulicic 0:c0ecb8bf28eb 28688 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28689 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28690 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28691 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28692 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28693 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28694 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28695 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28696 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28697 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28698 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28699 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28700 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28701
Marko Mikulicic 0:c0ecb8bf28eb 28702 #if V7_ENABLE__Object__getPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 28703 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28704 V7_PRIVATE enum v7_err Obj_getPrototypeOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28705 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28706 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28707
Marko Mikulicic 0:c0ecb8bf28eb 28708 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 28709 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 28710 v7_throwf(v7, TYPE_ERROR, "Object.getPrototypeOf called on non-object");
Marko Mikulicic 0:c0ecb8bf28eb 28711 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28712 }
Marko Mikulicic 0:c0ecb8bf28eb 28713 *res = v7_get_proto(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 28714
Marko Mikulicic 0:c0ecb8bf28eb 28715 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28716 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28717 }
Marko Mikulicic 0:c0ecb8bf28eb 28718 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28719
Marko Mikulicic 0:c0ecb8bf28eb 28720 #if V7_ENABLE__Object__isPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 28721 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28722 V7_PRIVATE enum v7_err Obj_isPrototypeOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28723 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28724 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28725 val_t proto = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 28726
Marko Mikulicic 0:c0ecb8bf28eb 28727 *res = v7_mk_boolean(v7, is_prototype_of(v7, obj, proto));
Marko Mikulicic 0:c0ecb8bf28eb 28728
Marko Mikulicic 0:c0ecb8bf28eb 28729 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28730 }
Marko Mikulicic 0:c0ecb8bf28eb 28731 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28732
Marko Mikulicic 0:c0ecb8bf28eb 28733 #if V7_ENABLE__Object__getOwnPropertyNames || V7_ENABLE__Object__keys
Marko Mikulicic 0:c0ecb8bf28eb 28734 /*
Marko Mikulicic 0:c0ecb8bf28eb 28735 * Hack to ensure that the iteration order of the keys array is consistent
Marko Mikulicic 0:c0ecb8bf28eb 28736 * with the iteration order if properties in `for in`
Marko Mikulicic 0:c0ecb8bf28eb 28737 * This will be obsoleted when arrays will have a special object type.
Marko Mikulicic 0:c0ecb8bf28eb 28738 */
Marko Mikulicic 0:c0ecb8bf28eb 28739 static void _Obj_append_reverse(struct v7 *v7, struct v7_property *p, val_t res,
Marko Mikulicic 0:c0ecb8bf28eb 28740 int i, v7_prop_attr_t ignore_flags) {
Marko Mikulicic 0:c0ecb8bf28eb 28741 while (p && p->attributes & ignore_flags) p = p->next;
Marko Mikulicic 0:c0ecb8bf28eb 28742 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 28743 if (p->next) _Obj_append_reverse(v7, p->next, res, i + 1, ignore_flags);
Marko Mikulicic 0:c0ecb8bf28eb 28744
Marko Mikulicic 0:c0ecb8bf28eb 28745 v7_array_set(v7, res, i, p->name);
Marko Mikulicic 0:c0ecb8bf28eb 28746 }
Marko Mikulicic 0:c0ecb8bf28eb 28747
Marko Mikulicic 0:c0ecb8bf28eb 28748 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28749 static enum v7_err _Obj_ownKeys(struct v7 *v7, unsigned int ignore_flags,
Marko Mikulicic 0:c0ecb8bf28eb 28750 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28751 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28752 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28753
Marko Mikulicic 0:c0ecb8bf28eb 28754 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 28755
Marko Mikulicic 0:c0ecb8bf28eb 28756 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 28757 rcode = v7_throwf(v7, TYPE_ERROR, "Object.keys called on non-object");
Marko Mikulicic 0:c0ecb8bf28eb 28758 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28759 }
Marko Mikulicic 0:c0ecb8bf28eb 28760
Marko Mikulicic 0:c0ecb8bf28eb 28761 _Obj_append_reverse(v7, get_object_struct(obj)->properties, *res, 0,
Marko Mikulicic 0:c0ecb8bf28eb 28762 ignore_flags);
Marko Mikulicic 0:c0ecb8bf28eb 28763
Marko Mikulicic 0:c0ecb8bf28eb 28764 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28765 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28766 }
Marko Mikulicic 0:c0ecb8bf28eb 28767 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28768
Marko Mikulicic 0:c0ecb8bf28eb 28769 #if V7_ENABLE__Object__hasOwnProperty || \
Marko Mikulicic 0:c0ecb8bf28eb 28770 V7_ENABLE__Object__propertyIsEnumerable || \
Marko Mikulicic 0:c0ecb8bf28eb 28771 V7_ENABLE__Object__getOwnPropertyDescriptor
Marko Mikulicic 0:c0ecb8bf28eb 28772 static enum v7_err _Obj_getOwnProperty(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 28773 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 28774 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28775 char name_buf[512];
Marko Mikulicic 0:c0ecb8bf28eb 28776 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 28777
Marko Mikulicic 0:c0ecb8bf28eb 28778 rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 28779 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28780 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28781 }
Marko Mikulicic 0:c0ecb8bf28eb 28782
Marko Mikulicic 0:c0ecb8bf28eb 28783 *res = v7_get_own_property(v7, obj, name_buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 28784
Marko Mikulicic 0:c0ecb8bf28eb 28785 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28786 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28787 }
Marko Mikulicic 0:c0ecb8bf28eb 28788 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28789
Marko Mikulicic 0:c0ecb8bf28eb 28790 #if V7_ENABLE__Object__keys
Marko Mikulicic 0:c0ecb8bf28eb 28791 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28792 V7_PRIVATE enum v7_err Obj_keys(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28793 return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE,
Marko Mikulicic 0:c0ecb8bf28eb 28794 res);
Marko Mikulicic 0:c0ecb8bf28eb 28795 }
Marko Mikulicic 0:c0ecb8bf28eb 28796 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28797
Marko Mikulicic 0:c0ecb8bf28eb 28798 #if V7_ENABLE__Object__getOwnPropertyNames
Marko Mikulicic 0:c0ecb8bf28eb 28799 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28800 V7_PRIVATE enum v7_err Obj_getOwnPropertyNames(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28801 return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN, res);
Marko Mikulicic 0:c0ecb8bf28eb 28802 }
Marko Mikulicic 0:c0ecb8bf28eb 28803 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28804
Marko Mikulicic 0:c0ecb8bf28eb 28805 #if V7_ENABLE__Object__getOwnPropertyDescriptor
Marko Mikulicic 0:c0ecb8bf28eb 28806 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28807 V7_PRIVATE enum v7_err Obj_getOwnPropertyDescriptor(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 28808 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28809 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28810 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 28811 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28812 val_t name = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 28813 val_t desc;
Marko Mikulicic 0:c0ecb8bf28eb 28814
Marko Mikulicic 0:c0ecb8bf28eb 28815 rcode = _Obj_getOwnProperty(v7, obj, name, &prop);
Marko Mikulicic 0:c0ecb8bf28eb 28816 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28817 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28818 }
Marko Mikulicic 0:c0ecb8bf28eb 28819
Marko Mikulicic 0:c0ecb8bf28eb 28820 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28821 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28822 }
Marko Mikulicic 0:c0ecb8bf28eb 28823
Marko Mikulicic 0:c0ecb8bf28eb 28824 desc = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 28825 v7_set(v7, desc, "value", 5, prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 28826 v7_set(v7, desc, "writable", 8,
Marko Mikulicic 0:c0ecb8bf28eb 28827 v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_WRITABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 28828 v7_set(v7, desc, "enumerable", 10,
Marko Mikulicic 0:c0ecb8bf28eb 28829 v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN |
Marko Mikulicic 0:c0ecb8bf28eb 28830 V7_PROPERTY_NON_ENUMERABLE))));
Marko Mikulicic 0:c0ecb8bf28eb 28831 v7_set(v7, desc, "configurable", 12,
Marko Mikulicic 0:c0ecb8bf28eb 28832 v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_CONFIGURABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 28833
Marko Mikulicic 0:c0ecb8bf28eb 28834 *res = desc;
Marko Mikulicic 0:c0ecb8bf28eb 28835
Marko Mikulicic 0:c0ecb8bf28eb 28836 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28837 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28838 }
Marko Mikulicic 0:c0ecb8bf28eb 28839 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28840
Marko Mikulicic 0:c0ecb8bf28eb 28841 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28842 static enum v7_err o_set_attr(struct v7 *v7, val_t desc, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 28843 size_t n, v7_prop_attr_desc_t *pattrs_delta,
Marko Mikulicic 0:c0ecb8bf28eb 28844 v7_prop_attr_desc_t flag_true,
Marko Mikulicic 0:c0ecb8bf28eb 28845 v7_prop_attr_desc_t flag_false) {
Marko Mikulicic 0:c0ecb8bf28eb 28846 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28847
Marko Mikulicic 0:c0ecb8bf28eb 28848 val_t v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 28849 rcode = v7_get_throwing(v7, desc, name, n, &v);
Marko Mikulicic 0:c0ecb8bf28eb 28850 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28851 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28852 }
Marko Mikulicic 0:c0ecb8bf28eb 28853
Marko Mikulicic 0:c0ecb8bf28eb 28854 if (v7_is_truthy(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 28855 *pattrs_delta |= flag_true;
Marko Mikulicic 0:c0ecb8bf28eb 28856 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28857 *pattrs_delta |= flag_false;
Marko Mikulicic 0:c0ecb8bf28eb 28858 }
Marko Mikulicic 0:c0ecb8bf28eb 28859
Marko Mikulicic 0:c0ecb8bf28eb 28860 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28861 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28862 }
Marko Mikulicic 0:c0ecb8bf28eb 28863
Marko Mikulicic 0:c0ecb8bf28eb 28864 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28865 static enum v7_err _Obj_defineProperty(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 28866 const char *name, int name_len,
Marko Mikulicic 0:c0ecb8bf28eb 28867 val_t desc, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28868 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28869 val_t val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 28870 v7_prop_attr_desc_t attrs_desc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28871
Marko Mikulicic 0:c0ecb8bf28eb 28872 /*
Marko Mikulicic 0:c0ecb8bf28eb 28873 * get provided value, or set `V7_DESC_PRESERVE_VALUE` flag if no value is
Marko Mikulicic 0:c0ecb8bf28eb 28874 * provided at all
Marko Mikulicic 0:c0ecb8bf28eb 28875 */
Marko Mikulicic 0:c0ecb8bf28eb 28876 {
Marko Mikulicic 0:c0ecb8bf28eb 28877 struct v7_property *prop = v7_get_property(v7, desc, "value", 5);
Marko Mikulicic 0:c0ecb8bf28eb 28878 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28879 /* no value is provided */
Marko Mikulicic 0:c0ecb8bf28eb 28880 attrs_desc |= V7_DESC_PRESERVE_VALUE;
Marko Mikulicic 0:c0ecb8bf28eb 28881 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28882 /* value is provided: use it */
Marko Mikulicic 0:c0ecb8bf28eb 28883 rcode = v7_property_value(v7, desc, prop, &val);
Marko Mikulicic 0:c0ecb8bf28eb 28884 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28885 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28886 }
Marko Mikulicic 0:c0ecb8bf28eb 28887 }
Marko Mikulicic 0:c0ecb8bf28eb 28888 }
Marko Mikulicic 0:c0ecb8bf28eb 28889
Marko Mikulicic 0:c0ecb8bf28eb 28890 /* Examine given properties, and set appropriate flags for `def_property` */
Marko Mikulicic 0:c0ecb8bf28eb 28891
Marko Mikulicic 0:c0ecb8bf28eb 28892 rcode = o_set_attr(v7, desc, "enumerable", 10, &attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 28893 V7_DESC_ENUMERABLE(1), V7_DESC_ENUMERABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 28894 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28895 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28896 }
Marko Mikulicic 0:c0ecb8bf28eb 28897
Marko Mikulicic 0:c0ecb8bf28eb 28898 rcode = o_set_attr(v7, desc, "writable", 8, &attrs_desc, V7_DESC_WRITABLE(1),
Marko Mikulicic 0:c0ecb8bf28eb 28899 V7_DESC_WRITABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 28900 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28901 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28902 }
Marko Mikulicic 0:c0ecb8bf28eb 28903
Marko Mikulicic 0:c0ecb8bf28eb 28904 rcode = o_set_attr(v7, desc, "configurable", 12, &attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 28905 V7_DESC_CONFIGURABLE(1), V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 28906 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28907 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28908 }
Marko Mikulicic 0:c0ecb8bf28eb 28909
Marko Mikulicic 0:c0ecb8bf28eb 28910 /* TODO(dfrank) : add getter/setter support */
Marko Mikulicic 0:c0ecb8bf28eb 28911
Marko Mikulicic 0:c0ecb8bf28eb 28912 /* Finally, do the job on defining the property */
Marko Mikulicic 0:c0ecb8bf28eb 28913 rcode = def_property(v7, obj, name, name_len, attrs_desc, val,
Marko Mikulicic 0:c0ecb8bf28eb 28914 0 /*not assign*/, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 28915 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28916 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28917 }
Marko Mikulicic 0:c0ecb8bf28eb 28918
Marko Mikulicic 0:c0ecb8bf28eb 28919 *res = obj;
Marko Mikulicic 0:c0ecb8bf28eb 28920 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28921
Marko Mikulicic 0:c0ecb8bf28eb 28922 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28923 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28924 }
Marko Mikulicic 0:c0ecb8bf28eb 28925
Marko Mikulicic 0:c0ecb8bf28eb 28926 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28927 V7_PRIVATE enum v7_err Obj_defineProperty(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28928 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28929 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28930 val_t name = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 28931 val_t desc = v7_arg(v7, 2);
Marko Mikulicic 0:c0ecb8bf28eb 28932 char name_buf[512];
Marko Mikulicic 0:c0ecb8bf28eb 28933 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 28934
Marko Mikulicic 0:c0ecb8bf28eb 28935 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 28936 rcode = v7_throwf(v7, TYPE_ERROR, "object expected");
Marko Mikulicic 0:c0ecb8bf28eb 28937 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28938 }
Marko Mikulicic 0:c0ecb8bf28eb 28939
Marko Mikulicic 0:c0ecb8bf28eb 28940 rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 28941 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28942 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28943 }
Marko Mikulicic 0:c0ecb8bf28eb 28944
Marko Mikulicic 0:c0ecb8bf28eb 28945 rcode = _Obj_defineProperty(v7, obj, name_buf, name_len, desc, res);
Marko Mikulicic 0:c0ecb8bf28eb 28946 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28947
Marko Mikulicic 0:c0ecb8bf28eb 28948 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28949 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28950 }
Marko Mikulicic 0:c0ecb8bf28eb 28951
Marko Mikulicic 0:c0ecb8bf28eb 28952 #if V7_ENABLE__Object__create || V7_ENABLE__Object__defineProperties
Marko Mikulicic 0:c0ecb8bf28eb 28953 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28954 static enum v7_err o_define_props(struct v7 *v7, val_t obj, val_t descs,
Marko Mikulicic 0:c0ecb8bf28eb 28955 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28956 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28957 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 28958
Marko Mikulicic 0:c0ecb8bf28eb 28959 if (!v7_is_object(descs)) {
Marko Mikulicic 0:c0ecb8bf28eb 28960 rcode = v7_throwf(v7, TYPE_ERROR, "object expected");
Marko Mikulicic 0:c0ecb8bf28eb 28961 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28962 }
Marko Mikulicic 0:c0ecb8bf28eb 28963
Marko Mikulicic 0:c0ecb8bf28eb 28964 for (p = get_object_struct(descs)->properties; p; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 28965 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 28966 const char *s = v7_get_string(v7, &p->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 28967 if (p->attributes & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 28968 continue;
Marko Mikulicic 0:c0ecb8bf28eb 28969 }
Marko Mikulicic 0:c0ecb8bf28eb 28970 rcode = _Obj_defineProperty(v7, obj, s, n, p->value, res);
Marko Mikulicic 0:c0ecb8bf28eb 28971 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28972 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28973 }
Marko Mikulicic 0:c0ecb8bf28eb 28974 }
Marko Mikulicic 0:c0ecb8bf28eb 28975
Marko Mikulicic 0:c0ecb8bf28eb 28976 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28977 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28978 }
Marko Mikulicic 0:c0ecb8bf28eb 28979 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28980
Marko Mikulicic 0:c0ecb8bf28eb 28981 #if V7_ENABLE__Object__defineProperties
Marko Mikulicic 0:c0ecb8bf28eb 28982 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28983 V7_PRIVATE enum v7_err Obj_defineProperties(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28984 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28985 val_t descs = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 28986
Marko Mikulicic 0:c0ecb8bf28eb 28987 *res = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28988 descs = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 28989 rcode = o_define_props(v7, *res, descs, res);
Marko Mikulicic 0:c0ecb8bf28eb 28990 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28991 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28992 }
Marko Mikulicic 0:c0ecb8bf28eb 28993
Marko Mikulicic 0:c0ecb8bf28eb 28994 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28995 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28996 }
Marko Mikulicic 0:c0ecb8bf28eb 28997 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28998
Marko Mikulicic 0:c0ecb8bf28eb 28999 #if V7_ENABLE__Object__create
Marko Mikulicic 0:c0ecb8bf28eb 29000 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29001 V7_PRIVATE enum v7_err Obj_create(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29002 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29003 val_t proto = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29004 val_t descs = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29005 if (!v7_is_null(proto) && !v7_is_object(proto)) {
Marko Mikulicic 0:c0ecb8bf28eb 29006 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 29007 "Object prototype may only be an Object or null");
Marko Mikulicic 0:c0ecb8bf28eb 29008 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29009 }
Marko Mikulicic 0:c0ecb8bf28eb 29010 *res = mk_object(v7, proto);
Marko Mikulicic 0:c0ecb8bf28eb 29011 if (v7_is_object(descs)) {
Marko Mikulicic 0:c0ecb8bf28eb 29012 rcode = o_define_props(v7, *res, descs, res);
Marko Mikulicic 0:c0ecb8bf28eb 29013 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29014 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29015 }
Marko Mikulicic 0:c0ecb8bf28eb 29016 }
Marko Mikulicic 0:c0ecb8bf28eb 29017
Marko Mikulicic 0:c0ecb8bf28eb 29018 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29019 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29020 }
Marko Mikulicic 0:c0ecb8bf28eb 29021 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29022
Marko Mikulicic 0:c0ecb8bf28eb 29023 #if V7_ENABLE__Object__propertyIsEnumerable
Marko Mikulicic 0:c0ecb8bf28eb 29024 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29025 V7_PRIVATE enum v7_err Obj_propertyIsEnumerable(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29026 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29027 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29028 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 29029 val_t name = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29030
Marko Mikulicic 0:c0ecb8bf28eb 29031 rcode = _Obj_getOwnProperty(v7, this_obj, name, &prop);
Marko Mikulicic 0:c0ecb8bf28eb 29032 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29033 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29034 }
Marko Mikulicic 0:c0ecb8bf28eb 29035
Marko Mikulicic 0:c0ecb8bf28eb 29036 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29037 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29038 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29039 *res =
Marko Mikulicic 0:c0ecb8bf28eb 29040 v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN |
Marko Mikulicic 0:c0ecb8bf28eb 29041 V7_PROPERTY_NON_ENUMERABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 29042 }
Marko Mikulicic 0:c0ecb8bf28eb 29043
Marko Mikulicic 0:c0ecb8bf28eb 29044 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29045
Marko Mikulicic 0:c0ecb8bf28eb 29046 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29047 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29048 }
Marko Mikulicic 0:c0ecb8bf28eb 29049 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29050
Marko Mikulicic 0:c0ecb8bf28eb 29051 #if V7_ENABLE__Object__hasOwnProperty
Marko Mikulicic 0:c0ecb8bf28eb 29052 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29053 V7_PRIVATE enum v7_err Obj_hasOwnProperty(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29054 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29055 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29056 val_t name = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29057 struct v7_property *ptmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 29058
Marko Mikulicic 0:c0ecb8bf28eb 29059 rcode = _Obj_getOwnProperty(v7, this_obj, name, &ptmp);
Marko Mikulicic 0:c0ecb8bf28eb 29060 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29061 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29062 }
Marko Mikulicic 0:c0ecb8bf28eb 29063
Marko Mikulicic 0:c0ecb8bf28eb 29064 *res = v7_mk_boolean(v7, ptmp != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29065 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29066
Marko Mikulicic 0:c0ecb8bf28eb 29067 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29068 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29069 }
Marko Mikulicic 0:c0ecb8bf28eb 29070 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29071
Marko Mikulicic 0:c0ecb8bf28eb 29072 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29073 V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29074 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29075 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29076 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 29077
Marko Mikulicic 0:c0ecb8bf28eb 29078 *res = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 29079
Marko Mikulicic 0:c0ecb8bf28eb 29080 if (v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29081 /* res is `this_obj` */
Marko Mikulicic 0:c0ecb8bf28eb 29082 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29083 }
Marko Mikulicic 0:c0ecb8bf28eb 29084
Marko Mikulicic 0:c0ecb8bf28eb 29085 p = v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 29086 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29087 *res = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 29088 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29089 }
Marko Mikulicic 0:c0ecb8bf28eb 29090
Marko Mikulicic 0:c0ecb8bf28eb 29091 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29092 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29093 }
Marko Mikulicic 0:c0ecb8bf28eb 29094
Marko Mikulicic 0:c0ecb8bf28eb 29095 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29096 V7_PRIVATE enum v7_err Obj_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29097 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29098 val_t ctor, name, this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29099 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 29100 const char *str = "Object";
Marko Mikulicic 0:c0ecb8bf28eb 29101 size_t name_len = ~0;
Marko Mikulicic 0:c0ecb8bf28eb 29102
Marko Mikulicic 0:c0ecb8bf28eb 29103 if (v7_is_undefined(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29104 str = "Undefined";
Marko Mikulicic 0:c0ecb8bf28eb 29105 } else if (v7_is_null(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29106 str = "Null";
Marko Mikulicic 0:c0ecb8bf28eb 29107 } else if (v7_is_number(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29108 str = "Number";
Marko Mikulicic 0:c0ecb8bf28eb 29109 } else if (v7_is_boolean(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29110 str = "Boolean";
Marko Mikulicic 0:c0ecb8bf28eb 29111 } else if (v7_is_string(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29112 str = "String";
Marko Mikulicic 0:c0ecb8bf28eb 29113 } else if (v7_is_callable(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29114 str = "Function";
Marko Mikulicic 0:c0ecb8bf28eb 29115 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29116 rcode = v7_get_throwing(v7, this_obj, "constructor", ~0, &ctor);
Marko Mikulicic 0:c0ecb8bf28eb 29117 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29118 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29119 }
Marko Mikulicic 0:c0ecb8bf28eb 29120
Marko Mikulicic 0:c0ecb8bf28eb 29121 if (!v7_is_undefined(ctor)) {
Marko Mikulicic 0:c0ecb8bf28eb 29122 rcode = v7_get_throwing(v7, ctor, "name", ~0, &name);
Marko Mikulicic 0:c0ecb8bf28eb 29123 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29124 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29125 }
Marko Mikulicic 0:c0ecb8bf28eb 29126
Marko Mikulicic 0:c0ecb8bf28eb 29127 if (!v7_is_undefined(name)) {
Marko Mikulicic 0:c0ecb8bf28eb 29128 size_t tmp_len;
Marko Mikulicic 0:c0ecb8bf28eb 29129 const char *tmp_str;
Marko Mikulicic 0:c0ecb8bf28eb 29130 tmp_str = v7_get_string(v7, &name, &tmp_len);
Marko Mikulicic 0:c0ecb8bf28eb 29131 /*
Marko Mikulicic 0:c0ecb8bf28eb 29132 * objects constructed with an anonymous constructor are represented as
Marko Mikulicic 0:c0ecb8bf28eb 29133 * Object, ch11/11.1/11.1.1/S11.1.1_A4.2.js
Marko Mikulicic 0:c0ecb8bf28eb 29134 */
Marko Mikulicic 0:c0ecb8bf28eb 29135 if (tmp_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 29136 str = tmp_str;
Marko Mikulicic 0:c0ecb8bf28eb 29137 name_len = tmp_len;
Marko Mikulicic 0:c0ecb8bf28eb 29138 }
Marko Mikulicic 0:c0ecb8bf28eb 29139 }
Marko Mikulicic 0:c0ecb8bf28eb 29140 }
Marko Mikulicic 0:c0ecb8bf28eb 29141 }
Marko Mikulicic 0:c0ecb8bf28eb 29142
Marko Mikulicic 0:c0ecb8bf28eb 29143 if (name_len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 29144 name_len = strlen(str);
Marko Mikulicic 0:c0ecb8bf28eb 29145 }
Marko Mikulicic 0:c0ecb8bf28eb 29146
Marko Mikulicic 0:c0ecb8bf28eb 29147 c_snprintf(buf, sizeof(buf), "[object %.*s]", (int) name_len, str);
Marko Mikulicic 0:c0ecb8bf28eb 29148 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 29149
Marko Mikulicic 0:c0ecb8bf28eb 29150 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29151 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29152 }
Marko Mikulicic 0:c0ecb8bf28eb 29153
Marko Mikulicic 0:c0ecb8bf28eb 29154 #if V7_ENABLE__Object__preventExtensions
Marko Mikulicic 0:c0ecb8bf28eb 29155 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29156 V7_PRIVATE enum v7_err Obj_preventExtensions(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29157 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29158 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29159 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29160 rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
Marko Mikulicic 0:c0ecb8bf28eb 29161 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29162 }
Marko Mikulicic 0:c0ecb8bf28eb 29163 get_object_struct(arg)->attributes |= V7_OBJ_NOT_EXTENSIBLE;
Marko Mikulicic 0:c0ecb8bf28eb 29164 *res = arg;
Marko Mikulicic 0:c0ecb8bf28eb 29165
Marko Mikulicic 0:c0ecb8bf28eb 29166 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29167 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29168 }
Marko Mikulicic 0:c0ecb8bf28eb 29169 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29170
Marko Mikulicic 0:c0ecb8bf28eb 29171 #if V7_ENABLE__Object__isExtensible
Marko Mikulicic 0:c0ecb8bf28eb 29172 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29173 V7_PRIVATE enum v7_err Obj_isExtensible(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29174 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29175 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29176
Marko Mikulicic 0:c0ecb8bf28eb 29177 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29178 rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
Marko Mikulicic 0:c0ecb8bf28eb 29179 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29180 }
Marko Mikulicic 0:c0ecb8bf28eb 29181
Marko Mikulicic 0:c0ecb8bf28eb 29182 *res = v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 29183 v7, !(get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE));
Marko Mikulicic 0:c0ecb8bf28eb 29184
Marko Mikulicic 0:c0ecb8bf28eb 29185 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29186 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29187 }
Marko Mikulicic 0:c0ecb8bf28eb 29188 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29189
Marko Mikulicic 0:c0ecb8bf28eb 29190 #if V7_ENABLE__Object__isFrozen || V7_ENABLE__Object__isSealed
Marko Mikulicic 0:c0ecb8bf28eb 29191 static enum v7_err is_rigid(struct v7 *v7, v7_val_t *res, int is_frozen) {
Marko Mikulicic 0:c0ecb8bf28eb 29192 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29193 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29194 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29195
Marko Mikulicic 0:c0ecb8bf28eb 29196 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29197 rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
Marko Mikulicic 0:c0ecb8bf28eb 29198 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29199 }
Marko Mikulicic 0:c0ecb8bf28eb 29200
Marko Mikulicic 0:c0ecb8bf28eb 29201 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29202
Marko Mikulicic 0:c0ecb8bf28eb 29203 if (get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
Marko Mikulicic 0:c0ecb8bf28eb 29204 v7_prop_attr_t attrs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29205 struct prop_iter_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 29206 memset(&ctx, 0, sizeof(ctx));
Marko Mikulicic 0:c0ecb8bf28eb 29207 V7_TRY2(init_prop_iter_ctx(v7, arg, 1, &ctx), clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 29208 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 29209 V7_TRY2(next_prop(v7, &ctx, NULL, NULL, &attrs, &ok), clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 29210 if (!ok) {
Marko Mikulicic 0:c0ecb8bf28eb 29211 break;
Marko Mikulicic 0:c0ecb8bf28eb 29212 }
Marko Mikulicic 0:c0ecb8bf28eb 29213 if (!(attrs & V7_PROPERTY_NON_CONFIGURABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 29214 goto clean_iter;
Marko Mikulicic 0:c0ecb8bf28eb 29215 }
Marko Mikulicic 0:c0ecb8bf28eb 29216 if (is_frozen) {
Marko Mikulicic 0:c0ecb8bf28eb 29217 if (!(attrs & V7_PROPERTY_SETTER) &&
Marko Mikulicic 0:c0ecb8bf28eb 29218 !(attrs & V7_PROPERTY_NON_WRITABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 29219 goto clean_iter;
Marko Mikulicic 0:c0ecb8bf28eb 29220 }
Marko Mikulicic 0:c0ecb8bf28eb 29221 }
Marko Mikulicic 0:c0ecb8bf28eb 29222 }
Marko Mikulicic 0:c0ecb8bf28eb 29223
Marko Mikulicic 0:c0ecb8bf28eb 29224 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29225
Marko Mikulicic 0:c0ecb8bf28eb 29226 clean_iter:
Marko Mikulicic 0:c0ecb8bf28eb 29227 v7_destruct_prop_iter_ctx(v7, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 29228 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29229 }
Marko Mikulicic 0:c0ecb8bf28eb 29230
Marko Mikulicic 0:c0ecb8bf28eb 29231 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29232 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29233 }
Marko Mikulicic 0:c0ecb8bf28eb 29234 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29235
Marko Mikulicic 0:c0ecb8bf28eb 29236 #if V7_ENABLE__Object__isSealed
Marko Mikulicic 0:c0ecb8bf28eb 29237 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29238 V7_PRIVATE enum v7_err Obj_isSealed(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29239 return is_rigid(v7, res, 0 /* is_frozen */);
Marko Mikulicic 0:c0ecb8bf28eb 29240 }
Marko Mikulicic 0:c0ecb8bf28eb 29241 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29242
Marko Mikulicic 0:c0ecb8bf28eb 29243 #if V7_ENABLE__Object__isFrozen
Marko Mikulicic 0:c0ecb8bf28eb 29244 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29245 V7_PRIVATE enum v7_err Obj_isFrozen(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29246 return is_rigid(v7, res, 1 /* is_frozen */);
Marko Mikulicic 0:c0ecb8bf28eb 29247 }
Marko Mikulicic 0:c0ecb8bf28eb 29248 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29249
Marko Mikulicic 0:c0ecb8bf28eb 29250 static const char js_function_Object[] =
Marko Mikulicic 0:c0ecb8bf28eb 29251 "function Object(v) {"
Marko Mikulicic 0:c0ecb8bf28eb 29252 "if (typeof v === 'boolean') return new Boolean(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29253 "if (typeof v === 'number') return new Number(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29254 "if (typeof v === 'string') return new String(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29255 "if (typeof v === 'date') return new Date(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29256 "}";
Marko Mikulicic 0:c0ecb8bf28eb 29257
Marko Mikulicic 0:c0ecb8bf28eb 29258 V7_PRIVATE void init_object(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29259 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29260 val_t object, v;
Marko Mikulicic 0:c0ecb8bf28eb 29261 /* TODO(mkm): initialize global object without requiring a parser */
Marko Mikulicic 0:c0ecb8bf28eb 29262 rcode = v7_exec(v7, js_function_Object, &v);
Marko Mikulicic 0:c0ecb8bf28eb 29263 assert(rcode == V7_OK);
Marko Mikulicic 0:c0ecb8bf28eb 29264 #if defined(NDEBUG)
Marko Mikulicic 0:c0ecb8bf28eb 29265 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29266 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29267
Marko Mikulicic 0:c0ecb8bf28eb 29268 object = v7_get(v7, v7->vals.global_object, "Object", 6);
Marko Mikulicic 0:c0ecb8bf28eb 29269 v7_set(v7, object, "prototype", 9, v7->vals.object_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29270 v7_def(v7, v7->vals.object_prototype, "constructor", 11,
Marko Mikulicic 0:c0ecb8bf28eb 29271 V7_DESC_ENUMERABLE(0), object);
Marko Mikulicic 0:c0ecb8bf28eb 29272
Marko Mikulicic 0:c0ecb8bf28eb 29273 set_method(v7, v7->vals.object_prototype, "toString", Obj_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29274 #if V7_ENABLE__Object__getPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 29275 set_cfunc_prop(v7, object, "getPrototypeOf", Obj_getPrototypeOf);
Marko Mikulicic 0:c0ecb8bf28eb 29276 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29277 #if V7_ENABLE__Object__getOwnPropertyDescriptor
Marko Mikulicic 0:c0ecb8bf28eb 29278 set_cfunc_prop(v7, object, "getOwnPropertyDescriptor",
Marko Mikulicic 0:c0ecb8bf28eb 29279 Obj_getOwnPropertyDescriptor);
Marko Mikulicic 0:c0ecb8bf28eb 29280 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29281
Marko Mikulicic 0:c0ecb8bf28eb 29282 /* defineProperty is currently required to perform stdlib initialization */
Marko Mikulicic 0:c0ecb8bf28eb 29283 set_method(v7, object, "defineProperty", Obj_defineProperty, 3);
Marko Mikulicic 0:c0ecb8bf28eb 29284
Marko Mikulicic 0:c0ecb8bf28eb 29285 #if V7_ENABLE__Object__defineProperties
Marko Mikulicic 0:c0ecb8bf28eb 29286 set_cfunc_prop(v7, object, "defineProperties", Obj_defineProperties);
Marko Mikulicic 0:c0ecb8bf28eb 29287 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29288 #if V7_ENABLE__Object__create
Marko Mikulicic 0:c0ecb8bf28eb 29289 set_cfunc_prop(v7, object, "create", Obj_create);
Marko Mikulicic 0:c0ecb8bf28eb 29290 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29291 #if V7_ENABLE__Object__keys
Marko Mikulicic 0:c0ecb8bf28eb 29292 set_cfunc_prop(v7, object, "keys", Obj_keys);
Marko Mikulicic 0:c0ecb8bf28eb 29293 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29294 #if V7_ENABLE__Object__getOwnPropertyNames
Marko Mikulicic 0:c0ecb8bf28eb 29295 set_cfunc_prop(v7, object, "getOwnPropertyNames", Obj_getOwnPropertyNames);
Marko Mikulicic 0:c0ecb8bf28eb 29296 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29297 #if V7_ENABLE__Object__preventExtensions
Marko Mikulicic 0:c0ecb8bf28eb 29298 set_method(v7, object, "preventExtensions", Obj_preventExtensions, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29299 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29300 #if V7_ENABLE__Object__isExtensible
Marko Mikulicic 0:c0ecb8bf28eb 29301 set_method(v7, object, "isExtensible", Obj_isExtensible, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29302 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29303 #if V7_ENABLE__Object__isSealed
Marko Mikulicic 0:c0ecb8bf28eb 29304 set_method(v7, object, "isSealed", Obj_isSealed, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29305 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29306 #if V7_ENABLE__Object__isFrozen
Marko Mikulicic 0:c0ecb8bf28eb 29307 set_method(v7, object, "isFrozen", Obj_isFrozen, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29308 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29309
Marko Mikulicic 0:c0ecb8bf28eb 29310 #if V7_ENABLE__Object__propertyIsEnumerable
Marko Mikulicic 0:c0ecb8bf28eb 29311 set_cfunc_prop(v7, v7->vals.object_prototype, "propertyIsEnumerable",
Marko Mikulicic 0:c0ecb8bf28eb 29312 Obj_propertyIsEnumerable);
Marko Mikulicic 0:c0ecb8bf28eb 29313 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29314 #if V7_ENABLE__Object__hasOwnProperty
Marko Mikulicic 0:c0ecb8bf28eb 29315 set_cfunc_prop(v7, v7->vals.object_prototype, "hasOwnProperty",
Marko Mikulicic 0:c0ecb8bf28eb 29316 Obj_hasOwnProperty);
Marko Mikulicic 0:c0ecb8bf28eb 29317 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29318 #if V7_ENABLE__Object__isPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 29319 set_cfunc_prop(v7, v7->vals.object_prototype, "isPrototypeOf",
Marko Mikulicic 0:c0ecb8bf28eb 29320 Obj_isPrototypeOf);
Marko Mikulicic 0:c0ecb8bf28eb 29321 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29322 set_cfunc_prop(v7, v7->vals.object_prototype, "valueOf", Obj_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 29323 }
Marko Mikulicic 0:c0ecb8bf28eb 29324 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29325 #line 1 "v7/src/std_error.c"
Marko Mikulicic 0:c0ecb8bf28eb 29326 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29327 /*
Marko Mikulicic 0:c0ecb8bf28eb 29328 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29329 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29330 */
Marko Mikulicic 0:c0ecb8bf28eb 29331
Marko Mikulicic 0:c0ecb8bf28eb 29332 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29333 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29334 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29335 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29336 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29337 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29338 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29339 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29340 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29341
Marko Mikulicic 0:c0ecb8bf28eb 29342 /*
Marko Mikulicic 0:c0ecb8bf28eb 29343 * TODO(dfrank): make the top of v7->call_frame to represent the current
Marko Mikulicic 0:c0ecb8bf28eb 29344 * frame, and thus get rid of the `CUR_LINENO()`
Marko Mikulicic 0:c0ecb8bf28eb 29345 */
Marko Mikulicic 0:c0ecb8bf28eb 29346 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 29347 #define CALLFRAME_LINENO(call_frame) ((call_frame)->line_no)
Marko Mikulicic 0:c0ecb8bf28eb 29348 #define CUR_LINENO() (v7->line_no)
Marko Mikulicic 0:c0ecb8bf28eb 29349 #else
Marko Mikulicic 0:c0ecb8bf28eb 29350 #define CALLFRAME_LINENO(call_frame) 0
Marko Mikulicic 0:c0ecb8bf28eb 29351 #define CUR_LINENO() 0
Marko Mikulicic 0:c0ecb8bf28eb 29352 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29353
Marko Mikulicic 0:c0ecb8bf28eb 29354 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29355 V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 29356
Marko Mikulicic 0:c0ecb8bf28eb 29357 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 29358 static int printf_stack_line(char *p, size_t len, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 29359 int line_no, const char *leading) {
Marko Mikulicic 0:c0ecb8bf28eb 29360 int ret;
Marko Mikulicic 0:c0ecb8bf28eb 29361 const char *fn = bcode_get_filename(bcode);
Marko Mikulicic 0:c0ecb8bf28eb 29362 if (fn == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29363 fn = "<no filename>";
Marko Mikulicic 0:c0ecb8bf28eb 29364 }
Marko Mikulicic 0:c0ecb8bf28eb 29365
Marko Mikulicic 0:c0ecb8bf28eb 29366 if (bcode->func_name_present) {
Marko Mikulicic 0:c0ecb8bf28eb 29367 /* this is a function's bcode: let's show the function's name as well */
Marko Mikulicic 0:c0ecb8bf28eb 29368 char *funcname;
Marko Mikulicic 0:c0ecb8bf28eb 29369
Marko Mikulicic 0:c0ecb8bf28eb 29370 /*
Marko Mikulicic 0:c0ecb8bf28eb 29371 * read first name from the bcode ops, which is the function name,
Marko Mikulicic 0:c0ecb8bf28eb 29372 * since `func_name_present` is set
Marko Mikulicic 0:c0ecb8bf28eb 29373 */
Marko Mikulicic 0:c0ecb8bf28eb 29374 bcode_next_name(bcode->ops.p, &funcname, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29375
Marko Mikulicic 0:c0ecb8bf28eb 29376 /* Check if it's an anonymous function */
Marko Mikulicic 0:c0ecb8bf28eb 29377 if (funcname[0] == '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 29378 funcname = (char *) "<anonymous>";
Marko Mikulicic 0:c0ecb8bf28eb 29379 }
Marko Mikulicic 0:c0ecb8bf28eb 29380 ret =
Marko Mikulicic 0:c0ecb8bf28eb 29381 snprintf(p, len, "%s at %s (%s:%d)", leading, funcname, fn, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 29382 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29383 /* it's a file's bcode: show only filename and line number */
Marko Mikulicic 0:c0ecb8bf28eb 29384 ret = snprintf(p, len, "%s at %s:%d", leading, fn, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 29385 }
Marko Mikulicic 0:c0ecb8bf28eb 29386 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 29387 }
Marko Mikulicic 0:c0ecb8bf28eb 29388
Marko Mikulicic 0:c0ecb8bf28eb 29389 static int printf_stack_line_cfunc(char *p, size_t len, v7_cfunction_t *cfunc,
Marko Mikulicic 0:c0ecb8bf28eb 29390 const char *leading) {
Marko Mikulicic 0:c0ecb8bf28eb 29391 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29392
Marko Mikulicic 0:c0ecb8bf28eb 29393 #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR)
Marko Mikulicic 0:c0ecb8bf28eb 29394 int name_len =
Marko Mikulicic 0:c0ecb8bf28eb 29395 snprintf(NULL, 0, "cfunc_%p", (void *) cfunc) + 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 29396 char *buf = (char *) malloc(name_len);
Marko Mikulicic 0:c0ecb8bf28eb 29397
Marko Mikulicic 0:c0ecb8bf28eb 29398 snprintf(buf, name_len, "cfunc_%p", (void *) cfunc);
Marko Mikulicic 0:c0ecb8bf28eb 29399 #else
Marko Mikulicic 0:c0ecb8bf28eb 29400 /*
Marko Mikulicic 0:c0ecb8bf28eb 29401 * We need this mode only for ecma test reporting, so that the
Marko Mikulicic 0:c0ecb8bf28eb 29402 * report is not different from one run to another
Marko Mikulicic 0:c0ecb8bf28eb 29403 */
Marko Mikulicic 0:c0ecb8bf28eb 29404 char *buf = (char *) "cfunc";
Marko Mikulicic 0:c0ecb8bf28eb 29405 (void) cfunc;
Marko Mikulicic 0:c0ecb8bf28eb 29406 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29407
Marko Mikulicic 0:c0ecb8bf28eb 29408 ret = snprintf(p, len, "%s at %s", leading, buf);
Marko Mikulicic 0:c0ecb8bf28eb 29409
Marko Mikulicic 0:c0ecb8bf28eb 29410 #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR)
Marko Mikulicic 0:c0ecb8bf28eb 29411 free(buf);
Marko Mikulicic 0:c0ecb8bf28eb 29412 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29413
Marko Mikulicic 0:c0ecb8bf28eb 29414 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 29415 }
Marko Mikulicic 0:c0ecb8bf28eb 29416
Marko Mikulicic 0:c0ecb8bf28eb 29417 static int print_stack_trace(char *p, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 29418 struct v7_call_frame_base *call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 29419 char *p_cur = p;
Marko Mikulicic 0:c0ecb8bf28eb 29420 int total_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29421
Marko Mikulicic 0:c0ecb8bf28eb 29422 assert(call_frame->type_mask == V7_CALL_FRAME_MASK_CFUNC &&
Marko Mikulicic 0:c0ecb8bf28eb 29423 ((struct v7_call_frame_cfunc *) call_frame)->cfunc == Error_ctor);
Marko Mikulicic 0:c0ecb8bf28eb 29424 call_frame = call_frame->prev;
Marko Mikulicic 0:c0ecb8bf28eb 29425
Marko Mikulicic 0:c0ecb8bf28eb 29426 while (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29427 int cur_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29428 const char *leading = (total_len ? "\n" : "");
Marko Mikulicic 0:c0ecb8bf28eb 29429 size_t line_len = len - (p_cur - p);
Marko Mikulicic 0:c0ecb8bf28eb 29430
Marko Mikulicic 0:c0ecb8bf28eb 29431 if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 29432 struct bcode *bcode = ((struct v7_call_frame_bcode *) call_frame)->bcode;
Marko Mikulicic 0:c0ecb8bf28eb 29433 if (bcode != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29434 cur_len = printf_stack_line(p_cur, line_len, bcode,
Marko Mikulicic 0:c0ecb8bf28eb 29435 CALLFRAME_LINENO(call_frame), leading);
Marko Mikulicic 0:c0ecb8bf28eb 29436 }
Marko Mikulicic 0:c0ecb8bf28eb 29437 } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 29438 cur_len = printf_stack_line_cfunc(
Marko Mikulicic 0:c0ecb8bf28eb 29439 p_cur, line_len, ((struct v7_call_frame_cfunc *) call_frame)->cfunc,
Marko Mikulicic 0:c0ecb8bf28eb 29440 leading);
Marko Mikulicic 0:c0ecb8bf28eb 29441 }
Marko Mikulicic 0:c0ecb8bf28eb 29442
Marko Mikulicic 0:c0ecb8bf28eb 29443 total_len += cur_len;
Marko Mikulicic 0:c0ecb8bf28eb 29444 if (p_cur != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29445 p_cur += cur_len;
Marko Mikulicic 0:c0ecb8bf28eb 29446 }
Marko Mikulicic 0:c0ecb8bf28eb 29447
Marko Mikulicic 0:c0ecb8bf28eb 29448 call_frame = call_frame->prev;
Marko Mikulicic 0:c0ecb8bf28eb 29449
Marko Mikulicic 0:c0ecb8bf28eb 29450 #if !(V7_ENABLE__StackTrace)
Marko Mikulicic 0:c0ecb8bf28eb 29451 break;
Marko Mikulicic 0:c0ecb8bf28eb 29452 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29453 }
Marko Mikulicic 0:c0ecb8bf28eb 29454
Marko Mikulicic 0:c0ecb8bf28eb 29455 return total_len;
Marko Mikulicic 0:c0ecb8bf28eb 29456 }
Marko Mikulicic 0:c0ecb8bf28eb 29457 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29458
Marko Mikulicic 0:c0ecb8bf28eb 29459 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29460 V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29461 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29462 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29463 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29464
Marko Mikulicic 0:c0ecb8bf28eb 29465 if (v7_is_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 29466 *res = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 29467 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29468 *res = mk_object(v7, v7->vals.error_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29469 }
Marko Mikulicic 0:c0ecb8bf28eb 29470 /* TODO(mkm): set non enumerable but provide toString method */
Marko Mikulicic 0:c0ecb8bf28eb 29471 v7_set(v7, *res, "message", 7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 29472
Marko Mikulicic 0:c0ecb8bf28eb 29473 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 29474 /* Save the stack trace */
Marko Mikulicic 0:c0ecb8bf28eb 29475 {
Marko Mikulicic 0:c0ecb8bf28eb 29476 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29477 val_t st_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 29478
Marko Mikulicic 0:c0ecb8bf28eb 29479 v7_own(v7, &st_v);
Marko Mikulicic 0:c0ecb8bf28eb 29480
Marko Mikulicic 0:c0ecb8bf28eb 29481 len = print_stack_trace(NULL, 0, v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 29482
Marko Mikulicic 0:c0ecb8bf28eb 29483 if (len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 29484 /* Now, create a placeholder for string */
Marko Mikulicic 0:c0ecb8bf28eb 29485 st_v = v7_mk_string(v7, NULL, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29486 len += 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 29487
Marko Mikulicic 0:c0ecb8bf28eb 29488 /* And fill it with actual data */
Marko Mikulicic 0:c0ecb8bf28eb 29489 print_stack_trace((char *) v7_get_string(v7, &st_v, NULL), len,
Marko Mikulicic 0:c0ecb8bf28eb 29490 v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 29491
Marko Mikulicic 0:c0ecb8bf28eb 29492 v7_set(v7, *res, "stack", ~0, st_v);
Marko Mikulicic 0:c0ecb8bf28eb 29493 }
Marko Mikulicic 0:c0ecb8bf28eb 29494
Marko Mikulicic 0:c0ecb8bf28eb 29495 v7_disown(v7, &st_v);
Marko Mikulicic 0:c0ecb8bf28eb 29496 }
Marko Mikulicic 0:c0ecb8bf28eb 29497 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29498
Marko Mikulicic 0:c0ecb8bf28eb 29499 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29500 }
Marko Mikulicic 0:c0ecb8bf28eb 29501
Marko Mikulicic 0:c0ecb8bf28eb 29502 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29503 V7_PRIVATE enum v7_err Error_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29504 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29505 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29506 val_t prefix, msg = v7_get(v7, this_obj, "message", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 29507
Marko Mikulicic 0:c0ecb8bf28eb 29508 if (!v7_is_string(msg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29509 *res = v7_mk_string(v7, "Error", ~0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29510 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29511 }
Marko Mikulicic 0:c0ecb8bf28eb 29512
Marko Mikulicic 0:c0ecb8bf28eb 29513 prefix = v7_mk_string(v7, "Error: ", ~0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29514 *res = s_concat(v7, prefix, msg);
Marko Mikulicic 0:c0ecb8bf28eb 29515 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29516
Marko Mikulicic 0:c0ecb8bf28eb 29517 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29518 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29519 }
Marko Mikulicic 0:c0ecb8bf28eb 29520
Marko Mikulicic 0:c0ecb8bf28eb 29521 static const char *const error_names[] = {TYPE_ERROR, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 29522 REFERENCE_ERROR, INTERNAL_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 29523 RANGE_ERROR, EVAL_ERROR};
Marko Mikulicic 0:c0ecb8bf28eb 29524
Marko Mikulicic 0:c0ecb8bf28eb 29525 V7_STATIC_ASSERT(ARRAY_SIZE(error_names) == ERROR_CTOR_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 29526 error_name_count_mismatch);
Marko Mikulicic 0:c0ecb8bf28eb 29527
Marko Mikulicic 0:c0ecb8bf28eb 29528 V7_PRIVATE void init_error(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29529 val_t error;
Marko Mikulicic 0:c0ecb8bf28eb 29530 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 29531
Marko Mikulicic 0:c0ecb8bf28eb 29532 error =
Marko Mikulicic 0:c0ecb8bf28eb 29533 mk_cfunction_obj_with_proto(v7, Error_ctor, 1, v7->vals.error_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29534 v7_def(v7, v7->vals.global_object, "Error", 5, V7_DESC_ENUMERABLE(0), error);
Marko Mikulicic 0:c0ecb8bf28eb 29535 set_method(v7, v7->vals.error_prototype, "toString", Error_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29536
Marko Mikulicic 0:c0ecb8bf28eb 29537 for (i = 0; i < ARRAY_SIZE(error_names); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 29538 error = mk_cfunction_obj_with_proto(
Marko Mikulicic 0:c0ecb8bf28eb 29539 v7, Error_ctor, 1, mk_object(v7, v7->vals.error_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 29540 v7_def(v7, v7->vals.global_object, error_names[i], strlen(error_names[i]),
Marko Mikulicic 0:c0ecb8bf28eb 29541 V7_DESC_ENUMERABLE(0), error);
Marko Mikulicic 0:c0ecb8bf28eb 29542 v7->vals.error_objects[i] = error;
Marko Mikulicic 0:c0ecb8bf28eb 29543 }
Marko Mikulicic 0:c0ecb8bf28eb 29544 }
Marko Mikulicic 0:c0ecb8bf28eb 29545 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29546 #line 1 "v7/src/std_number.c"
Marko Mikulicic 0:c0ecb8bf28eb 29547 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29548 /*
Marko Mikulicic 0:c0ecb8bf28eb 29549 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29550 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29551 */
Marko Mikulicic 0:c0ecb8bf28eb 29552
Marko Mikulicic 0:c0ecb8bf28eb 29553 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29554 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29555 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29556 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29557 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29558 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29559 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29560 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29561 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29562
Marko Mikulicic 0:c0ecb8bf28eb 29563 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29564 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 29565 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29566
Marko Mikulicic 0:c0ecb8bf28eb 29567 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29568 V7_PRIVATE enum v7_err Number_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29569 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29570 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29571 val_t arg0 = v7_argc(v7) == 0 ? v7_mk_number(v7, 0.0) : v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29572
Marko Mikulicic 0:c0ecb8bf28eb 29573 if (v7_is_number(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 29574 *res = arg0;
Marko Mikulicic 0:c0ecb8bf28eb 29575 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29576 rcode = to_number_v(v7, arg0, res);
Marko Mikulicic 0:c0ecb8bf28eb 29577 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29578 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29579 }
Marko Mikulicic 0:c0ecb8bf28eb 29580 }
Marko Mikulicic 0:c0ecb8bf28eb 29581
Marko Mikulicic 0:c0ecb8bf28eb 29582 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 29583 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 29584 get_object_struct(v7->vals.number_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 29585 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 29586
Marko Mikulicic 0:c0ecb8bf28eb 29587 /*
Marko Mikulicic 0:c0ecb8bf28eb 29588 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 29589 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 29590 */
Marko Mikulicic 0:c0ecb8bf28eb 29591 }
Marko Mikulicic 0:c0ecb8bf28eb 29592
Marko Mikulicic 0:c0ecb8bf28eb 29593 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29594 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29595 }
Marko Mikulicic 0:c0ecb8bf28eb 29596
Marko Mikulicic 0:c0ecb8bf28eb 29597 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29598 V7_PRIVATE enum v7_err n_to_str(struct v7 *v7, const char *format, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29599 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29600 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29601 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29602 int len, digits = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29603 char fmt[10], buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 29604
Marko Mikulicic 0:c0ecb8bf28eb 29605 rcode = to_number_v(v7, arg0, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 29606 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29607 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29608 }
Marko Mikulicic 0:c0ecb8bf28eb 29609
Marko Mikulicic 0:c0ecb8bf28eb 29610 if (v7_get_double(v7, arg0) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 29611 digits = (int) v7_get_double(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 29612 }
Marko Mikulicic 0:c0ecb8bf28eb 29613
Marko Mikulicic 0:c0ecb8bf28eb 29614 /*
Marko Mikulicic 0:c0ecb8bf28eb 29615 * NOTE: we don't own `arg0` and `this_obj`, since this function is called
Marko Mikulicic 0:c0ecb8bf28eb 29616 * from cfunctions only, and GC is inhibited during these calls
Marko Mikulicic 0:c0ecb8bf28eb 29617 */
Marko Mikulicic 0:c0ecb8bf28eb 29618
Marko Mikulicic 0:c0ecb8bf28eb 29619 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29620 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29621 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29622 }
Marko Mikulicic 0:c0ecb8bf28eb 29623
Marko Mikulicic 0:c0ecb8bf28eb 29624 snprintf(fmt, sizeof(fmt), format, digits);
Marko Mikulicic 0:c0ecb8bf28eb 29625 len = snprintf(buf, sizeof(buf), fmt, v7_get_double(v7, this_obj));
Marko Mikulicic 0:c0ecb8bf28eb 29626
Marko Mikulicic 0:c0ecb8bf28eb 29627 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29628
Marko Mikulicic 0:c0ecb8bf28eb 29629 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29630 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29631 }
Marko Mikulicic 0:c0ecb8bf28eb 29632
Marko Mikulicic 0:c0ecb8bf28eb 29633 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29634 V7_PRIVATE enum v7_err Number_toFixed(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29635 return n_to_str(v7, "%%.%dlf", res);
Marko Mikulicic 0:c0ecb8bf28eb 29636 }
Marko Mikulicic 0:c0ecb8bf28eb 29637
Marko Mikulicic 0:c0ecb8bf28eb 29638 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29639 V7_PRIVATE enum v7_err Number_toExp(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29640 return n_to_str(v7, "%%.%de", res);
Marko Mikulicic 0:c0ecb8bf28eb 29641 }
Marko Mikulicic 0:c0ecb8bf28eb 29642
Marko Mikulicic 0:c0ecb8bf28eb 29643 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29644 V7_PRIVATE enum v7_err Number_toPrecision(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29645 return Number_toExp(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 29646 }
Marko Mikulicic 0:c0ecb8bf28eb 29647
Marko Mikulicic 0:c0ecb8bf28eb 29648 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29649 V7_PRIVATE enum v7_err Number_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29650 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29651 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29652
Marko Mikulicic 0:c0ecb8bf28eb 29653 if (!v7_is_number(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29654 (v7_is_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29655 v7_get_proto(v7, this_obj) != v7->vals.number_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 29656 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 29657 v7_throwf(v7, TYPE_ERROR, "Number.valueOf called on non-number object");
Marko Mikulicic 0:c0ecb8bf28eb 29658 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29659 }
Marko Mikulicic 0:c0ecb8bf28eb 29660
Marko Mikulicic 0:c0ecb8bf28eb 29661 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 29662 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29663 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29664 }
Marko Mikulicic 0:c0ecb8bf28eb 29665
Marko Mikulicic 0:c0ecb8bf28eb 29666 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29667 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29668 }
Marko Mikulicic 0:c0ecb8bf28eb 29669
Marko Mikulicic 0:c0ecb8bf28eb 29670 /*
Marko Mikulicic 0:c0ecb8bf28eb 29671 * Converts a 64 bit signed integer into a string of a given base.
Marko Mikulicic 0:c0ecb8bf28eb 29672 * Requires space for 65 bytes (64 bit + null terminator) in the result buffer
Marko Mikulicic 0:c0ecb8bf28eb 29673 */
Marko Mikulicic 0:c0ecb8bf28eb 29674 static char *cs_itoa(int64_t value, char *result, int base) {
Marko Mikulicic 0:c0ecb8bf28eb 29675 char *ptr = result, *ptr1 = result, tmp_char;
Marko Mikulicic 0:c0ecb8bf28eb 29676 int64_t tmp_value;
Marko Mikulicic 0:c0ecb8bf28eb 29677 int64_t sign = value < 0 ? -1 : 1;
Marko Mikulicic 0:c0ecb8bf28eb 29678 const char *base36 = "0123456789abcdefghijklmnopqrstuvwxyz";
Marko Mikulicic 0:c0ecb8bf28eb 29679
Marko Mikulicic 0:c0ecb8bf28eb 29680 if (base < 2 || base > 36) {
Marko Mikulicic 0:c0ecb8bf28eb 29681 *result = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 29682 return result;
Marko Mikulicic 0:c0ecb8bf28eb 29683 }
Marko Mikulicic 0:c0ecb8bf28eb 29684
Marko Mikulicic 0:c0ecb8bf28eb 29685 /* let's think positive */
Marko Mikulicic 0:c0ecb8bf28eb 29686 value = value * sign;
Marko Mikulicic 0:c0ecb8bf28eb 29687 do {
Marko Mikulicic 0:c0ecb8bf28eb 29688 tmp_value = value;
Marko Mikulicic 0:c0ecb8bf28eb 29689 value /= base;
Marko Mikulicic 0:c0ecb8bf28eb 29690 *ptr++ = base36[tmp_value - value * base];
Marko Mikulicic 0:c0ecb8bf28eb 29691 } while (value);
Marko Mikulicic 0:c0ecb8bf28eb 29692
Marko Mikulicic 0:c0ecb8bf28eb 29693 /* sign */
Marko Mikulicic 0:c0ecb8bf28eb 29694 if (sign < 0) *ptr++ = '-';
Marko Mikulicic 0:c0ecb8bf28eb 29695 *ptr-- = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 29696 while (ptr1 < ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 29697 tmp_char = *ptr;
Marko Mikulicic 0:c0ecb8bf28eb 29698 *ptr-- = *ptr1;
Marko Mikulicic 0:c0ecb8bf28eb 29699 *ptr1++ = tmp_char;
Marko Mikulicic 0:c0ecb8bf28eb 29700 }
Marko Mikulicic 0:c0ecb8bf28eb 29701 return result;
Marko Mikulicic 0:c0ecb8bf28eb 29702 }
Marko Mikulicic 0:c0ecb8bf28eb 29703
Marko Mikulicic 0:c0ecb8bf28eb 29704 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29705 V7_PRIVATE enum v7_err Number_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29706 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29707 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29708 val_t radixv = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29709 char buf[65];
Marko Mikulicic 0:c0ecb8bf28eb 29710 double d, radix;
Marko Mikulicic 0:c0ecb8bf28eb 29711
Marko Mikulicic 0:c0ecb8bf28eb 29712 if (this_obj == v7->vals.number_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 29713 *res = v7_mk_string(v7, "0", 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29714 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29715 }
Marko Mikulicic 0:c0ecb8bf28eb 29716
Marko Mikulicic 0:c0ecb8bf28eb 29717 /* Make sure this function was called on Number instance */
Marko Mikulicic 0:c0ecb8bf28eb 29718 if (!v7_is_number(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29719 !(v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29720 is_prototype_of(v7, this_obj, v7->vals.number_prototype))) {
Marko Mikulicic 0:c0ecb8bf28eb 29721 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 29722 "Number.toString called on non-number object");
Marko Mikulicic 0:c0ecb8bf28eb 29723 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29724 }
Marko Mikulicic 0:c0ecb8bf28eb 29725
Marko Mikulicic 0:c0ecb8bf28eb 29726 /* Get number primitive */
Marko Mikulicic 0:c0ecb8bf28eb 29727 rcode = to_number_v(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29728 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29729 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29730 }
Marko Mikulicic 0:c0ecb8bf28eb 29731
Marko Mikulicic 0:c0ecb8bf28eb 29732 /* Get radix if provided, or 10 otherwise */
Marko Mikulicic 0:c0ecb8bf28eb 29733 if (!v7_is_undefined(radixv)) {
Marko Mikulicic 0:c0ecb8bf28eb 29734 rcode = to_number_v(v7, radixv, &radixv);
Marko Mikulicic 0:c0ecb8bf28eb 29735 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29736 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29737 }
Marko Mikulicic 0:c0ecb8bf28eb 29738 radix = v7_get_double(v7, radixv);
Marko Mikulicic 0:c0ecb8bf28eb 29739 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29740 radix = 10.0;
Marko Mikulicic 0:c0ecb8bf28eb 29741 }
Marko Mikulicic 0:c0ecb8bf28eb 29742
Marko Mikulicic 0:c0ecb8bf28eb 29743 d = v7_get_double(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29744 if (!isnan(d) && (int64_t) d == d && radix >= 2) {
Marko Mikulicic 0:c0ecb8bf28eb 29745 cs_itoa(d, buf, radix);
Marko Mikulicic 0:c0ecb8bf28eb 29746 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 29747 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29748 rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29749 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29750 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29751 }
Marko Mikulicic 0:c0ecb8bf28eb 29752 }
Marko Mikulicic 0:c0ecb8bf28eb 29753
Marko Mikulicic 0:c0ecb8bf28eb 29754 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29755 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29756 }
Marko Mikulicic 0:c0ecb8bf28eb 29757
Marko Mikulicic 0:c0ecb8bf28eb 29758 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29759 V7_PRIVATE enum v7_err n_isNaN(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29760 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29761 *res = v7_mk_boolean(v7, !v7_is_number(arg0) || arg0 == V7_TAG_NAN);
Marko Mikulicic 0:c0ecb8bf28eb 29762 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29763 }
Marko Mikulicic 0:c0ecb8bf28eb 29764
Marko Mikulicic 0:c0ecb8bf28eb 29765 V7_PRIVATE void init_number(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29766 v7_prop_attr_desc_t attrs_desc =
Marko Mikulicic 0:c0ecb8bf28eb 29767 (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 29768 val_t num = mk_cfunction_obj_with_proto(v7, Number_ctor, 1,
Marko Mikulicic 0:c0ecb8bf28eb 29769 v7->vals.number_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29770
Marko Mikulicic 0:c0ecb8bf28eb 29771 v7_def(v7, v7->vals.global_object, "Number", 6, V7_DESC_ENUMERABLE(0), num);
Marko Mikulicic 0:c0ecb8bf28eb 29772
Marko Mikulicic 0:c0ecb8bf28eb 29773 set_cfunc_prop(v7, v7->vals.number_prototype, "toFixed", Number_toFixed);
Marko Mikulicic 0:c0ecb8bf28eb 29774 set_cfunc_prop(v7, v7->vals.number_prototype, "toPrecision",
Marko Mikulicic 0:c0ecb8bf28eb 29775 Number_toPrecision);
Marko Mikulicic 0:c0ecb8bf28eb 29776 set_cfunc_prop(v7, v7->vals.number_prototype, "toExponential", Number_toExp);
Marko Mikulicic 0:c0ecb8bf28eb 29777 set_cfunc_prop(v7, v7->vals.number_prototype, "valueOf", Number_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 29778 set_cfunc_prop(v7, v7->vals.number_prototype, "toString", Number_toString);
Marko Mikulicic 0:c0ecb8bf28eb 29779
Marko Mikulicic 0:c0ecb8bf28eb 29780 v7_def(v7, num, "MAX_VALUE", 9, attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 29781 v7_mk_number(v7, 1.7976931348623157e+308));
Marko Mikulicic 0:c0ecb8bf28eb 29782 v7_def(v7, num, "MIN_VALUE", 9, attrs_desc, v7_mk_number(v7, 5e-324));
Marko Mikulicic 0:c0ecb8bf28eb 29783 #if V7_ENABLE__NUMBER__NEGATIVE_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 29784 v7_def(v7, num, "NEGATIVE_INFINITY", 17, attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 29785 v7_mk_number(v7, -INFINITY));
Marko Mikulicic 0:c0ecb8bf28eb 29786 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29787 #if V7_ENABLE__NUMBER__POSITIVE_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 29788 v7_def(v7, num, "POSITIVE_INFINITY", 17, attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 29789 v7_mk_number(v7, INFINITY));
Marko Mikulicic 0:c0ecb8bf28eb 29790 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29791 v7_def(v7, num, "NaN", 3, attrs_desc, V7_TAG_NAN);
Marko Mikulicic 0:c0ecb8bf28eb 29792
Marko Mikulicic 0:c0ecb8bf28eb 29793 v7_def(v7, v7->vals.global_object, "NaN", 3, attrs_desc, V7_TAG_NAN);
Marko Mikulicic 0:c0ecb8bf28eb 29794 v7_def(v7, v7->vals.global_object, "isNaN", 5, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 29795 v7_mk_cfunction(n_isNaN));
Marko Mikulicic 0:c0ecb8bf28eb 29796 }
Marko Mikulicic 0:c0ecb8bf28eb 29797
Marko Mikulicic 0:c0ecb8bf28eb 29798 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29799 }
Marko Mikulicic 0:c0ecb8bf28eb 29800 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29801 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29802 #line 1 "v7/src/std_json.c"
Marko Mikulicic 0:c0ecb8bf28eb 29803 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29804 /*
Marko Mikulicic 0:c0ecb8bf28eb 29805 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29806 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29807 */
Marko Mikulicic 0:c0ecb8bf28eb 29808
Marko Mikulicic 0:c0ecb8bf28eb 29809 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29810 /* Amalgamated: #include "v7/src/stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29811 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29812 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29813 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29814 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29815 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29816
Marko Mikulicic 0:c0ecb8bf28eb 29817 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29818 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 29819 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29820
Marko Mikulicic 0:c0ecb8bf28eb 29821 #if defined(V7_ALT_JSON_PARSE)
Marko Mikulicic 0:c0ecb8bf28eb 29822 extern enum v7_err v7_alt_json_parse(struct v7 *v7, v7_val_t json_string,
Marko Mikulicic 0:c0ecb8bf28eb 29823 v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 29824 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29825
Marko Mikulicic 0:c0ecb8bf28eb 29826 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29827 V7_PRIVATE enum v7_err Json_stringify(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29828 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29829 char buf[100], *p = v7_to_json(v7, arg0, buf, sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 29830 *res = v7_mk_string(v7, p, strlen(p), 1);
Marko Mikulicic 0:c0ecb8bf28eb 29831
Marko Mikulicic 0:c0ecb8bf28eb 29832 if (p != buf) free(p);
Marko Mikulicic 0:c0ecb8bf28eb 29833 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29834 }
Marko Mikulicic 0:c0ecb8bf28eb 29835
Marko Mikulicic 0:c0ecb8bf28eb 29836 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29837 V7_PRIVATE enum v7_err Json_parse(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29838 v7_val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29839 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29840 #if defined(V7_ALT_JSON_PARSE)
Marko Mikulicic 0:c0ecb8bf28eb 29841 rcode = v7_alt_json_parse(v7, arg, res);
Marko Mikulicic 0:c0ecb8bf28eb 29842 #else
Marko Mikulicic 0:c0ecb8bf28eb 29843 rcode = std_eval(v7, arg, V7_UNDEFINED, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 29844 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29845 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29846 }
Marko Mikulicic 0:c0ecb8bf28eb 29847
Marko Mikulicic 0:c0ecb8bf28eb 29848 V7_PRIVATE void init_json(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29849 val_t o = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29850 set_method(v7, o, "stringify", Json_stringify, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29851 set_method(v7, o, "parse", Json_parse, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29852 v7_def(v7, v7->vals.global_object, "JSON", 4, V7_DESC_ENUMERABLE(0), o);
Marko Mikulicic 0:c0ecb8bf28eb 29853 }
Marko Mikulicic 0:c0ecb8bf28eb 29854
Marko Mikulicic 0:c0ecb8bf28eb 29855 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29856 }
Marko Mikulicic 0:c0ecb8bf28eb 29857 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29858 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29859 #line 1 "v7/src/std_array.c"
Marko Mikulicic 0:c0ecb8bf28eb 29860 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29861 /*
Marko Mikulicic 0:c0ecb8bf28eb 29862 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29863 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29864 */
Marko Mikulicic 0:c0ecb8bf28eb 29865
Marko Mikulicic 0:c0ecb8bf28eb 29866 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29867 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29868 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29869 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29870 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29871 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29872 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29873 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29874 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29875 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29876 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29877
Marko Mikulicic 0:c0ecb8bf28eb 29878 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29879 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 29880 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29881
Marko Mikulicic 0:c0ecb8bf28eb 29882 struct a_sort_data {
Marko Mikulicic 0:c0ecb8bf28eb 29883 val_t sort_func;
Marko Mikulicic 0:c0ecb8bf28eb 29884 };
Marko Mikulicic 0:c0ecb8bf28eb 29885
Marko Mikulicic 0:c0ecb8bf28eb 29886 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29887 V7_PRIVATE enum v7_err Array_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29888 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29889 unsigned long i, len;
Marko Mikulicic 0:c0ecb8bf28eb 29890
Marko Mikulicic 0:c0ecb8bf28eb 29891 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 29892 *res = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29893 /*
Marko Mikulicic 0:c0ecb8bf28eb 29894 * The interpreter passes dense array to C functions.
Marko Mikulicic 0:c0ecb8bf28eb 29895 * However dense array implementation is not yet complete
Marko Mikulicic 0:c0ecb8bf28eb 29896 * so we don't want to propagate them at each call to Array()
Marko Mikulicic 0:c0ecb8bf28eb 29897 */
Marko Mikulicic 0:c0ecb8bf28eb 29898 len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29899 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 29900 rcode = v7_array_set_throwing(v7, *res, i, v7_arg(v7, i), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29901 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29902 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29903 }
Marko Mikulicic 0:c0ecb8bf28eb 29904 }
Marko Mikulicic 0:c0ecb8bf28eb 29905
Marko Mikulicic 0:c0ecb8bf28eb 29906 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29907 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29908 }
Marko Mikulicic 0:c0ecb8bf28eb 29909
Marko Mikulicic 0:c0ecb8bf28eb 29910 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29911 V7_PRIVATE enum v7_err Array_push(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29912 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29913 int i, len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29914
Marko Mikulicic 0:c0ecb8bf28eb 29915 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 29916
Marko Mikulicic 0:c0ecb8bf28eb 29917 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 29918 *res = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 29919 rcode = v7_array_push_throwing(v7, v7_get_this(v7), *res, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29920 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29921 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29922 }
Marko Mikulicic 0:c0ecb8bf28eb 29923 }
Marko Mikulicic 0:c0ecb8bf28eb 29924
Marko Mikulicic 0:c0ecb8bf28eb 29925 /*
Marko Mikulicic 0:c0ecb8bf28eb 29926 * TODO(dfrank) : we need to implement `length` as a real property, and here
Marko Mikulicic 0:c0ecb8bf28eb 29927 * we need to set new length and return it (even if the object is not an
Marko Mikulicic 0:c0ecb8bf28eb 29928 * array)
Marko Mikulicic 0:c0ecb8bf28eb 29929 */
Marko Mikulicic 0:c0ecb8bf28eb 29930
Marko Mikulicic 0:c0ecb8bf28eb 29931 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29932 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29933 }
Marko Mikulicic 0:c0ecb8bf28eb 29934
Marko Mikulicic 0:c0ecb8bf28eb 29935 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29936 V7_PRIVATE enum v7_err Array_get_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29937 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29938 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29939 long len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29940
Marko Mikulicic 0:c0ecb8bf28eb 29941 if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 29942 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29943 }
Marko Mikulicic 0:c0ecb8bf28eb 29944 *res = v7_mk_number(v7, len);
Marko Mikulicic 0:c0ecb8bf28eb 29945
Marko Mikulicic 0:c0ecb8bf28eb 29946 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29947 }
Marko Mikulicic 0:c0ecb8bf28eb 29948
Marko Mikulicic 0:c0ecb8bf28eb 29949 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29950 V7_PRIVATE enum v7_err Array_set_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29951 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29952 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29953 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29954 long new_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29955
Marko Mikulicic 0:c0ecb8bf28eb 29956 rcode = to_long(v7, v7_arg(v7, 0), -1, &new_len);
Marko Mikulicic 0:c0ecb8bf28eb 29957 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29958 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29959 }
Marko Mikulicic 0:c0ecb8bf28eb 29960
Marko Mikulicic 0:c0ecb8bf28eb 29961 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29962 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 29963 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29964 } else if (new_len < 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 29965 (v7_is_number(arg0) && (isnan(v7_get_double(v7, arg0)) ||
Marko Mikulicic 0:c0ecb8bf28eb 29966 isinf(v7_get_double(v7, arg0))))) {
Marko Mikulicic 0:c0ecb8bf28eb 29967 rcode = v7_throwf(v7, RANGE_ERROR, "Invalid array length");
Marko Mikulicic 0:c0ecb8bf28eb 29968 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29969 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29970 struct v7_property **p, **next;
Marko Mikulicic 0:c0ecb8bf28eb 29971 long index, max_index = -1;
Marko Mikulicic 0:c0ecb8bf28eb 29972
Marko Mikulicic 0:c0ecb8bf28eb 29973 /* Remove all items with an index higher than new_len */
Marko Mikulicic 0:c0ecb8bf28eb 29974 for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) {
Marko Mikulicic 0:c0ecb8bf28eb 29975 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 29976 const char *s = v7_get_string(v7, &p[0]->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 29977 next = &p[0]->next;
Marko Mikulicic 0:c0ecb8bf28eb 29978 index = strtol(s, NULL, 10);
Marko Mikulicic 0:c0ecb8bf28eb 29979 if (index >= new_len) {
Marko Mikulicic 0:c0ecb8bf28eb 29980 v7_destroy_property(p);
Marko Mikulicic 0:c0ecb8bf28eb 29981 *p = *next;
Marko Mikulicic 0:c0ecb8bf28eb 29982 next = p;
Marko Mikulicic 0:c0ecb8bf28eb 29983 } else if (index > max_index) {
Marko Mikulicic 0:c0ecb8bf28eb 29984 max_index = index;
Marko Mikulicic 0:c0ecb8bf28eb 29985 }
Marko Mikulicic 0:c0ecb8bf28eb 29986 }
Marko Mikulicic 0:c0ecb8bf28eb 29987
Marko Mikulicic 0:c0ecb8bf28eb 29988 /* If we have to expand, insert an item with appropriate index */
Marko Mikulicic 0:c0ecb8bf28eb 29989 if (new_len > 0 && max_index < new_len - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 29990 char buf[40];
Marko Mikulicic 0:c0ecb8bf28eb 29991 c_snprintf(buf, sizeof(buf), "%ld", new_len - 1);
Marko Mikulicic 0:c0ecb8bf28eb 29992 v7_set(v7, this_obj, buf, strlen(buf), V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 29993 }
Marko Mikulicic 0:c0ecb8bf28eb 29994 }
Marko Mikulicic 0:c0ecb8bf28eb 29995
Marko Mikulicic 0:c0ecb8bf28eb 29996 *res = v7_mk_number(v7, new_len);
Marko Mikulicic 0:c0ecb8bf28eb 29997
Marko Mikulicic 0:c0ecb8bf28eb 29998 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29999 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30000 }
Marko Mikulicic 0:c0ecb8bf28eb 30001
Marko Mikulicic 0:c0ecb8bf28eb 30002 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30003 static enum v7_err a_cmp(struct v7 *v7, void *user_data, const void *pa,
Marko Mikulicic 0:c0ecb8bf28eb 30004 const void *pb, int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30005 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30006 struct a_sort_data *sort_data = (struct a_sort_data *) user_data;
Marko Mikulicic 0:c0ecb8bf28eb 30007 val_t a = *(val_t *) pa, b = *(val_t *) pb, func = sort_data->sort_func;
Marko Mikulicic 0:c0ecb8bf28eb 30008
Marko Mikulicic 0:c0ecb8bf28eb 30009 if (v7_is_callable(v7, func)) {
Marko Mikulicic 0:c0ecb8bf28eb 30010 int saved_inhibit_gc = v7->inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 30011 val_t vres = V7_UNDEFINED, args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30012 v7_array_push(v7, args, a);
Marko Mikulicic 0:c0ecb8bf28eb 30013 v7_array_push(v7, args, b);
Marko Mikulicic 0:c0ecb8bf28eb 30014 v7->inhibit_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30015 rcode = b_apply(v7, func, V7_UNDEFINED, args, 0, &vres);
Marko Mikulicic 0:c0ecb8bf28eb 30016 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30017 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30018 }
Marko Mikulicic 0:c0ecb8bf28eb 30019 v7->inhibit_gc = saved_inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 30020 *res = (int) -v7_get_double(v7, vres);
Marko Mikulicic 0:c0ecb8bf28eb 30021 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30022 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30023 char sa[100], sb[100];
Marko Mikulicic 0:c0ecb8bf28eb 30024
Marko Mikulicic 0:c0ecb8bf28eb 30025 rcode = to_string(v7, a, NULL, sa, sizeof(sa), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30026 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30027 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30028 }
Marko Mikulicic 0:c0ecb8bf28eb 30029
Marko Mikulicic 0:c0ecb8bf28eb 30030 rcode = to_string(v7, b, NULL, sb, sizeof(sb), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30031 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30032 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30033 }
Marko Mikulicic 0:c0ecb8bf28eb 30034
Marko Mikulicic 0:c0ecb8bf28eb 30035 sa[sizeof(sa) - 1] = sb[sizeof(sb) - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 30036 *res = strcmp(sb, sa);
Marko Mikulicic 0:c0ecb8bf28eb 30037 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30038 }
Marko Mikulicic 0:c0ecb8bf28eb 30039
Marko Mikulicic 0:c0ecb8bf28eb 30040 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30041 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30042 }
Marko Mikulicic 0:c0ecb8bf28eb 30043
Marko Mikulicic 0:c0ecb8bf28eb 30044 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30045 static enum v7_err a_partition(struct v7 *v7, val_t *a, int l, int r,
Marko Mikulicic 0:c0ecb8bf28eb 30046 void *user_data, int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30047 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30048 val_t t, pivot = a[l];
Marko Mikulicic 0:c0ecb8bf28eb 30049 int i = l, j = r + 1;
Marko Mikulicic 0:c0ecb8bf28eb 30050
Marko Mikulicic 0:c0ecb8bf28eb 30051 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 30052 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 30053 ++i;
Marko Mikulicic 0:c0ecb8bf28eb 30054
Marko Mikulicic 0:c0ecb8bf28eb 30055 if (i <= r) {
Marko Mikulicic 0:c0ecb8bf28eb 30056 int tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30057 rcode = a_cmp(v7, user_data, &a[i], &pivot, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 30058 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30059 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30060 }
Marko Mikulicic 0:c0ecb8bf28eb 30061
Marko Mikulicic 0:c0ecb8bf28eb 30062 if (tmp > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30063 break;
Marko Mikulicic 0:c0ecb8bf28eb 30064 }
Marko Mikulicic 0:c0ecb8bf28eb 30065 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30066 break;
Marko Mikulicic 0:c0ecb8bf28eb 30067 }
Marko Mikulicic 0:c0ecb8bf28eb 30068 }
Marko Mikulicic 0:c0ecb8bf28eb 30069 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 30070 int tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30071 --j;
Marko Mikulicic 0:c0ecb8bf28eb 30072
Marko Mikulicic 0:c0ecb8bf28eb 30073 rcode = a_cmp(v7, user_data, &a[j], &pivot, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 30074 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30075 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30076 }
Marko Mikulicic 0:c0ecb8bf28eb 30077
Marko Mikulicic 0:c0ecb8bf28eb 30078 if (tmp <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30079 break;
Marko Mikulicic 0:c0ecb8bf28eb 30080 }
Marko Mikulicic 0:c0ecb8bf28eb 30081 }
Marko Mikulicic 0:c0ecb8bf28eb 30082 if (i >= j) break;
Marko Mikulicic 0:c0ecb8bf28eb 30083 t = a[i];
Marko Mikulicic 0:c0ecb8bf28eb 30084 a[i] = a[j];
Marko Mikulicic 0:c0ecb8bf28eb 30085 a[j] = t;
Marko Mikulicic 0:c0ecb8bf28eb 30086 }
Marko Mikulicic 0:c0ecb8bf28eb 30087 t = a[l];
Marko Mikulicic 0:c0ecb8bf28eb 30088 a[l] = a[j];
Marko Mikulicic 0:c0ecb8bf28eb 30089 a[j] = t;
Marko Mikulicic 0:c0ecb8bf28eb 30090
Marko Mikulicic 0:c0ecb8bf28eb 30091 *res = j;
Marko Mikulicic 0:c0ecb8bf28eb 30092 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30093 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30094 }
Marko Mikulicic 0:c0ecb8bf28eb 30095
Marko Mikulicic 0:c0ecb8bf28eb 30096 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30097 static enum v7_err a_qsort(struct v7 *v7, val_t *a, int l, int r,
Marko Mikulicic 0:c0ecb8bf28eb 30098 void *user_data) {
Marko Mikulicic 0:c0ecb8bf28eb 30099 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30100 if (l < r) {
Marko Mikulicic 0:c0ecb8bf28eb 30101 int j = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30102 rcode = a_partition(v7, a, l, r, user_data, &j);
Marko Mikulicic 0:c0ecb8bf28eb 30103 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30104 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30105 }
Marko Mikulicic 0:c0ecb8bf28eb 30106
Marko Mikulicic 0:c0ecb8bf28eb 30107 rcode = a_qsort(v7, a, l, j - 1, user_data);
Marko Mikulicic 0:c0ecb8bf28eb 30108 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30109 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30110 }
Marko Mikulicic 0:c0ecb8bf28eb 30111
Marko Mikulicic 0:c0ecb8bf28eb 30112 rcode = a_qsort(v7, a, j + 1, r, user_data);
Marko Mikulicic 0:c0ecb8bf28eb 30113 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30114 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30115 }
Marko Mikulicic 0:c0ecb8bf28eb 30116 }
Marko Mikulicic 0:c0ecb8bf28eb 30117 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30118 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30119 }
Marko Mikulicic 0:c0ecb8bf28eb 30120
Marko Mikulicic 0:c0ecb8bf28eb 30121 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30122 static enum v7_err a_sort(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 30123 enum v7_err (*sorting_func)(struct v7 *v7, void *,
Marko Mikulicic 0:c0ecb8bf28eb 30124 const void *,
Marko Mikulicic 0:c0ecb8bf28eb 30125 const void *, int *res),
Marko Mikulicic 0:c0ecb8bf28eb 30126 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30127 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30128 int i = 0, len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30129 val_t *arr = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 30130 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30131
Marko Mikulicic 0:c0ecb8bf28eb 30132 *res = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30133 len = v7_array_length(v7, *res);
Marko Mikulicic 0:c0ecb8bf28eb 30134
Marko Mikulicic 0:c0ecb8bf28eb 30135 if (!v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 30136 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30137 }
Marko Mikulicic 0:c0ecb8bf28eb 30138
Marko Mikulicic 0:c0ecb8bf28eb 30139 arr = (val_t *) malloc(len * sizeof(arr[0]));
Marko Mikulicic 0:c0ecb8bf28eb 30140
Marko Mikulicic 0:c0ecb8bf28eb 30141 assert(*res != v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 30142
Marko Mikulicic 0:c0ecb8bf28eb 30143 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30144 arr[i] = v7_array_get(v7, *res, i);
Marko Mikulicic 0:c0ecb8bf28eb 30145 }
Marko Mikulicic 0:c0ecb8bf28eb 30146
Marko Mikulicic 0:c0ecb8bf28eb 30147 /* TODO(dfrank): sorting_func isn't actually used! something is wrong here */
Marko Mikulicic 0:c0ecb8bf28eb 30148 if (sorting_func != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30149 struct a_sort_data sort_data;
Marko Mikulicic 0:c0ecb8bf28eb 30150 sort_data.sort_func = arg0;
Marko Mikulicic 0:c0ecb8bf28eb 30151 rcode = a_qsort(v7, arr, 0, len - 1, &sort_data);
Marko Mikulicic 0:c0ecb8bf28eb 30152 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30153 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30154 }
Marko Mikulicic 0:c0ecb8bf28eb 30155 }
Marko Mikulicic 0:c0ecb8bf28eb 30156
Marko Mikulicic 0:c0ecb8bf28eb 30157 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30158 v7_array_set(v7, *res, i, arr[len - (i + 1)]);
Marko Mikulicic 0:c0ecb8bf28eb 30159 }
Marko Mikulicic 0:c0ecb8bf28eb 30160
Marko Mikulicic 0:c0ecb8bf28eb 30161 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30162 if (arr != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30163 free(arr);
Marko Mikulicic 0:c0ecb8bf28eb 30164 }
Marko Mikulicic 0:c0ecb8bf28eb 30165 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30166 }
Marko Mikulicic 0:c0ecb8bf28eb 30167
Marko Mikulicic 0:c0ecb8bf28eb 30168 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30169 V7_PRIVATE enum v7_err Array_sort(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30170 return a_sort(v7, a_cmp, res);
Marko Mikulicic 0:c0ecb8bf28eb 30171 }
Marko Mikulicic 0:c0ecb8bf28eb 30172
Marko Mikulicic 0:c0ecb8bf28eb 30173 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30174 V7_PRIVATE enum v7_err Array_reverse(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30175 return a_sort(v7, NULL, res);
Marko Mikulicic 0:c0ecb8bf28eb 30176 }
Marko Mikulicic 0:c0ecb8bf28eb 30177
Marko Mikulicic 0:c0ecb8bf28eb 30178 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30179 V7_PRIVATE enum v7_err Array_join(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30180 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30181 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30182 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30183 size_t sep_size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30184 const char *sep = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 30185
Marko Mikulicic 0:c0ecb8bf28eb 30186 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 30187
Marko Mikulicic 0:c0ecb8bf28eb 30188 /* Get pointer to the separator string */
Marko Mikulicic 0:c0ecb8bf28eb 30189 if (!v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 30190 /* If no separator is provided, use comma */
Marko Mikulicic 0:c0ecb8bf28eb 30191 arg0 = v7_mk_string(v7, ",", 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30192 }
Marko Mikulicic 0:c0ecb8bf28eb 30193 sep = v7_get_string(v7, &arg0, &sep_size);
Marko Mikulicic 0:c0ecb8bf28eb 30194
Marko Mikulicic 0:c0ecb8bf28eb 30195 /* Do the actual join */
Marko Mikulicic 0:c0ecb8bf28eb 30196 if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 30197 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 30198 char buf[100], *p;
Marko Mikulicic 0:c0ecb8bf28eb 30199 long i, n, num_elems = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30200
Marko Mikulicic 0:c0ecb8bf28eb 30201 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30202
Marko Mikulicic 0:c0ecb8bf28eb 30203 for (i = 0; i < num_elems; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30204 /* Append separator */
Marko Mikulicic 0:c0ecb8bf28eb 30205 if (i > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30206 mbuf_append(&m, sep, sep_size);
Marko Mikulicic 0:c0ecb8bf28eb 30207 }
Marko Mikulicic 0:c0ecb8bf28eb 30208
Marko Mikulicic 0:c0ecb8bf28eb 30209 /* Append next item from an array */
Marko Mikulicic 0:c0ecb8bf28eb 30210 p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 30211 {
Marko Mikulicic 0:c0ecb8bf28eb 30212 size_t tmp;
Marko Mikulicic 0:c0ecb8bf28eb 30213 rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, buf,
Marko Mikulicic 0:c0ecb8bf28eb 30214 sizeof(buf), &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 30215 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30216 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30217 }
Marko Mikulicic 0:c0ecb8bf28eb 30218 n = tmp;
Marko Mikulicic 0:c0ecb8bf28eb 30219 }
Marko Mikulicic 0:c0ecb8bf28eb 30220 if (n > (long) sizeof(buf)) {
Marko Mikulicic 0:c0ecb8bf28eb 30221 p = (char *) malloc(n + 1);
Marko Mikulicic 0:c0ecb8bf28eb 30222 rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, p, n, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30223 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30224 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30225 }
Marko Mikulicic 0:c0ecb8bf28eb 30226 }
Marko Mikulicic 0:c0ecb8bf28eb 30227 mbuf_append(&m, p, n);
Marko Mikulicic 0:c0ecb8bf28eb 30228 if (p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 30229 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 30230 }
Marko Mikulicic 0:c0ecb8bf28eb 30231 }
Marko Mikulicic 0:c0ecb8bf28eb 30232
Marko Mikulicic 0:c0ecb8bf28eb 30233 /* mbuf contains concatenated string now. Copy it to the result. */
Marko Mikulicic 0:c0ecb8bf28eb 30234 *res = v7_mk_string(v7, m.buf, m.len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30235 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 30236 }
Marko Mikulicic 0:c0ecb8bf28eb 30237
Marko Mikulicic 0:c0ecb8bf28eb 30238 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30239 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30240 }
Marko Mikulicic 0:c0ecb8bf28eb 30241
Marko Mikulicic 0:c0ecb8bf28eb 30242 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30243 V7_PRIVATE enum v7_err Array_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30244 return Array_join(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 30245 }
Marko Mikulicic 0:c0ecb8bf28eb 30246
Marko Mikulicic 0:c0ecb8bf28eb 30247 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30248 static enum v7_err a_splice(struct v7 *v7, int mutate, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30249 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30250 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30251 long i, len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30252 long num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30253 long elems_to_insert = num_args > 2 ? num_args - 2 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 30254 long arg0, arg1;
Marko Mikulicic 0:c0ecb8bf28eb 30255
Marko Mikulicic 0:c0ecb8bf28eb 30256 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30257 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 30258 "Array.splice or Array.slice called on non-object value");
Marko Mikulicic 0:c0ecb8bf28eb 30259 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30260 }
Marko Mikulicic 0:c0ecb8bf28eb 30261
Marko Mikulicic 0:c0ecb8bf28eb 30262 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30263
Marko Mikulicic 0:c0ecb8bf28eb 30264 rcode = to_long(v7, v7_arg(v7, 0), 0, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30265 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30266 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30267 }
Marko Mikulicic 0:c0ecb8bf28eb 30268
Marko Mikulicic 0:c0ecb8bf28eb 30269 rcode = to_long(v7, v7_arg(v7, 1), len, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30270 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30271 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30272 }
Marko Mikulicic 0:c0ecb8bf28eb 30273
Marko Mikulicic 0:c0ecb8bf28eb 30274 /* Bounds check */
Marko Mikulicic 0:c0ecb8bf28eb 30275 if (!mutate && len <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30276 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30277 }
Marko Mikulicic 0:c0ecb8bf28eb 30278 if (arg0 < 0) arg0 = len + arg0;
Marko Mikulicic 0:c0ecb8bf28eb 30279 if (arg0 < 0) arg0 = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30280 if (arg0 > len) arg0 = len;
Marko Mikulicic 0:c0ecb8bf28eb 30281 if (mutate) {
Marko Mikulicic 0:c0ecb8bf28eb 30282 if (arg1 < 0) arg1 = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30283 arg1 += arg0;
Marko Mikulicic 0:c0ecb8bf28eb 30284 } else if (arg1 < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30285 arg1 = len + arg1;
Marko Mikulicic 0:c0ecb8bf28eb 30286 }
Marko Mikulicic 0:c0ecb8bf28eb 30287
Marko Mikulicic 0:c0ecb8bf28eb 30288 /* Create return value - slice */
Marko Mikulicic 0:c0ecb8bf28eb 30289 for (i = arg0; i < arg1 && i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30290 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 30291 v7_array_push_throwing(v7, *res, v7_array_get(v7, this_obj, i), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30292 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30293 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30294 }
Marko Mikulicic 0:c0ecb8bf28eb 30295 }
Marko Mikulicic 0:c0ecb8bf28eb 30296
Marko Mikulicic 0:c0ecb8bf28eb 30297 if (mutate && get_object_struct(this_obj)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 30298 /*
Marko Mikulicic 0:c0ecb8bf28eb 30299 * dense arrays are spliced by memmoving leaving the trailing
Marko Mikulicic 0:c0ecb8bf28eb 30300 * space allocated for future appends.
Marko Mikulicic 0:c0ecb8bf28eb 30301 * TODO(mkm): figure out if trimming is better
Marko Mikulicic 0:c0ecb8bf28eb 30302 */
Marko Mikulicic 0:c0ecb8bf28eb 30303 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 30304 v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 30305 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 30306 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30307 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30308 }
Marko Mikulicic 0:c0ecb8bf28eb 30309 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 30310 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30311 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30312 }
Marko Mikulicic 0:c0ecb8bf28eb 30313
Marko Mikulicic 0:c0ecb8bf28eb 30314 memmove(abuf->buf + arg0 * sizeof(val_t), abuf->buf + arg1 * sizeof(val_t),
Marko Mikulicic 0:c0ecb8bf28eb 30315 (len - arg1) * sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 30316 abuf->len -= (arg1 - arg0) * sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 30317 } else if (mutate) {
Marko Mikulicic 0:c0ecb8bf28eb 30318 /* If splicing, modify this_obj array: remove spliced sub-array */
Marko Mikulicic 0:c0ecb8bf28eb 30319 struct v7_property **p, **next;
Marko Mikulicic 0:c0ecb8bf28eb 30320 long i;
Marko Mikulicic 0:c0ecb8bf28eb 30321
Marko Mikulicic 0:c0ecb8bf28eb 30322 for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) {
Marko Mikulicic 0:c0ecb8bf28eb 30323 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 30324 const char *s = v7_get_string(v7, &p[0]->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 30325 next = &p[0]->next;
Marko Mikulicic 0:c0ecb8bf28eb 30326 i = strtol(s, NULL, 10);
Marko Mikulicic 0:c0ecb8bf28eb 30327 if (i >= arg0 && i < arg1) {
Marko Mikulicic 0:c0ecb8bf28eb 30328 /* Remove items from spliced sub-array */
Marko Mikulicic 0:c0ecb8bf28eb 30329 v7_destroy_property(p);
Marko Mikulicic 0:c0ecb8bf28eb 30330 *p = *next;
Marko Mikulicic 0:c0ecb8bf28eb 30331 next = p;
Marko Mikulicic 0:c0ecb8bf28eb 30332 } else if (i >= arg1) {
Marko Mikulicic 0:c0ecb8bf28eb 30333 /* Modify indices of the elements past sub-array */
Marko Mikulicic 0:c0ecb8bf28eb 30334 char key[20];
Marko Mikulicic 0:c0ecb8bf28eb 30335 size_t n = c_snprintf(key, sizeof(key), "%ld",
Marko Mikulicic 0:c0ecb8bf28eb 30336 i - (arg1 - arg0) + elems_to_insert);
Marko Mikulicic 0:c0ecb8bf28eb 30337 p[0]->name = v7_mk_string(v7, key, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30338 }
Marko Mikulicic 0:c0ecb8bf28eb 30339 }
Marko Mikulicic 0:c0ecb8bf28eb 30340
Marko Mikulicic 0:c0ecb8bf28eb 30341 /* Insert optional extra elements */
Marko Mikulicic 0:c0ecb8bf28eb 30342 for (i = 2; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30343 char key[20];
Marko Mikulicic 0:c0ecb8bf28eb 30344 size_t n = c_snprintf(key, sizeof(key), "%ld", arg0 + i - 2);
Marko Mikulicic 0:c0ecb8bf28eb 30345 rcode = set_property(v7, this_obj, key, n, v7_arg(v7, i), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30346 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30347 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30348 }
Marko Mikulicic 0:c0ecb8bf28eb 30349 }
Marko Mikulicic 0:c0ecb8bf28eb 30350 }
Marko Mikulicic 0:c0ecb8bf28eb 30351
Marko Mikulicic 0:c0ecb8bf28eb 30352 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30353 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30354 }
Marko Mikulicic 0:c0ecb8bf28eb 30355
Marko Mikulicic 0:c0ecb8bf28eb 30356 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30357 V7_PRIVATE enum v7_err Array_slice(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30358 return a_splice(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 30359 }
Marko Mikulicic 0:c0ecb8bf28eb 30360
Marko Mikulicic 0:c0ecb8bf28eb 30361 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30362 V7_PRIVATE enum v7_err Array_splice(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30363 return a_splice(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 30364 }
Marko Mikulicic 0:c0ecb8bf28eb 30365
Marko Mikulicic 0:c0ecb8bf28eb 30366 static void a_prep1(struct v7 *v7, val_t t, val_t *a0, val_t *a1) {
Marko Mikulicic 0:c0ecb8bf28eb 30367 *a0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30368 *a1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30369 if (v7_is_undefined(*a1)) {
Marko Mikulicic 0:c0ecb8bf28eb 30370 *a1 = t;
Marko Mikulicic 0:c0ecb8bf28eb 30371 }
Marko Mikulicic 0:c0ecb8bf28eb 30372 }
Marko Mikulicic 0:c0ecb8bf28eb 30373
Marko Mikulicic 0:c0ecb8bf28eb 30374 /*
Marko Mikulicic 0:c0ecb8bf28eb 30375 * Call callback function `cb`, passing `this_obj` as `this`, with the
Marko Mikulicic 0:c0ecb8bf28eb 30376 * following arguments:
Marko Mikulicic 0:c0ecb8bf28eb 30377 *
Marko Mikulicic 0:c0ecb8bf28eb 30378 * cb(v, n, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30379 *
Marko Mikulicic 0:c0ecb8bf28eb 30380 */
Marko Mikulicic 0:c0ecb8bf28eb 30381 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30382 static enum v7_err a_prep2(struct v7 *v7, val_t cb, val_t v, val_t n,
Marko Mikulicic 0:c0ecb8bf28eb 30383 val_t this_obj, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30384 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30385 int saved_inhibit_gc = v7->inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 30386 val_t args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30387
Marko Mikulicic 0:c0ecb8bf28eb 30388 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30389
Marko Mikulicic 0:c0ecb8bf28eb 30390 v7_own(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 30391
Marko Mikulicic 0:c0ecb8bf28eb 30392 v7_array_push(v7, args, v);
Marko Mikulicic 0:c0ecb8bf28eb 30393 v7_array_push(v7, args, n);
Marko Mikulicic 0:c0ecb8bf28eb 30394 v7_array_push(v7, args, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30395
Marko Mikulicic 0:c0ecb8bf28eb 30396 v7->inhibit_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30397 rcode = b_apply(v7, cb, this_obj, args, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 30398 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30399 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30400 }
Marko Mikulicic 0:c0ecb8bf28eb 30401
Marko Mikulicic 0:c0ecb8bf28eb 30402 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30403 v7->inhibit_gc = saved_inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 30404 v7_disown(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 30405
Marko Mikulicic 0:c0ecb8bf28eb 30406 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30407 }
Marko Mikulicic 0:c0ecb8bf28eb 30408
Marko Mikulicic 0:c0ecb8bf28eb 30409 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30410 V7_PRIVATE enum v7_err Array_forEach(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30411 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30412 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30413 val_t v = V7_UNDEFINED, cb = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30414 unsigned long len, i;
Marko Mikulicic 0:c0ecb8bf28eb 30415 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30416 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30417 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30418
Marko Mikulicic 0:c0ecb8bf28eb 30419 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30420 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30421 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30422 }
Marko Mikulicic 0:c0ecb8bf28eb 30423
Marko Mikulicic 0:c0ecb8bf28eb 30424 if (!v7_is_callable(v7, cb)) {
Marko Mikulicic 0:c0ecb8bf28eb 30425 rcode = v7_throwf(v7, TYPE_ERROR, "Function expected");
Marko Mikulicic 0:c0ecb8bf28eb 30426 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30427 }
Marko Mikulicic 0:c0ecb8bf28eb 30428
Marko Mikulicic 0:c0ecb8bf28eb 30429 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30430
Marko Mikulicic 0:c0ecb8bf28eb 30431 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30432 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30433 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30434 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30435
Marko Mikulicic 0:c0ecb8bf28eb 30436 rcode = a_prep2(v7, cb, v, v7_mk_number(v7, i), this_obj, res);
Marko Mikulicic 0:c0ecb8bf28eb 30437 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30438 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30439 }
Marko Mikulicic 0:c0ecb8bf28eb 30440 }
Marko Mikulicic 0:c0ecb8bf28eb 30441
Marko Mikulicic 0:c0ecb8bf28eb 30442 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30443 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30444 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30445 }
Marko Mikulicic 0:c0ecb8bf28eb 30446
Marko Mikulicic 0:c0ecb8bf28eb 30447 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30448 V7_PRIVATE enum v7_err Array_map(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30449 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30450 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30451 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30452 unsigned long len, i;
Marko Mikulicic 0:c0ecb8bf28eb 30453 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30454 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30455 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30456
Marko Mikulicic 0:c0ecb8bf28eb 30457 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30458 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30459 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30460 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30461 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30462 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30463 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30464
Marko Mikulicic 0:c0ecb8bf28eb 30465 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30466 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30467 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30468
Marko Mikulicic 0:c0ecb8bf28eb 30469 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30470 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30471 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30472 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30473 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30474 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30475 }
Marko Mikulicic 0:c0ecb8bf28eb 30476
Marko Mikulicic 0:c0ecb8bf28eb 30477 rcode = v7_array_set_throwing(v7, *res, i, el, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30478 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30479 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30480 }
Marko Mikulicic 0:c0ecb8bf28eb 30481 }
Marko Mikulicic 0:c0ecb8bf28eb 30482 }
Marko Mikulicic 0:c0ecb8bf28eb 30483
Marko Mikulicic 0:c0ecb8bf28eb 30484 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30485 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30486 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30487 }
Marko Mikulicic 0:c0ecb8bf28eb 30488
Marko Mikulicic 0:c0ecb8bf28eb 30489 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30490 V7_PRIVATE enum v7_err Array_every(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30491 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30492 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30493 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30494 unsigned long i, len;
Marko Mikulicic 0:c0ecb8bf28eb 30495 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30496 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30497 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30498
Marko Mikulicic 0:c0ecb8bf28eb 30499 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30500
Marko Mikulicic 0:c0ecb8bf28eb 30501 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30502 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30503 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30504 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30505 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30506
Marko Mikulicic 0:c0ecb8bf28eb 30507 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30508 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30509 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30510
Marko Mikulicic 0:c0ecb8bf28eb 30511 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30512 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30513 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30514 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30515 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30516 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30517 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30518 }
Marko Mikulicic 0:c0ecb8bf28eb 30519 if (!v7_is_truthy(v7, el)) {
Marko Mikulicic 0:c0ecb8bf28eb 30520 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30521 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30522 }
Marko Mikulicic 0:c0ecb8bf28eb 30523 }
Marko Mikulicic 0:c0ecb8bf28eb 30524 }
Marko Mikulicic 0:c0ecb8bf28eb 30525
Marko Mikulicic 0:c0ecb8bf28eb 30526 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30527
Marko Mikulicic 0:c0ecb8bf28eb 30528 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30529 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30530 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30531 }
Marko Mikulicic 0:c0ecb8bf28eb 30532
Marko Mikulicic 0:c0ecb8bf28eb 30533 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30534 V7_PRIVATE enum v7_err Array_some(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30535 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30536 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30537 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30538 unsigned long i, len;
Marko Mikulicic 0:c0ecb8bf28eb 30539 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30540 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30541 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30542
Marko Mikulicic 0:c0ecb8bf28eb 30543 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30544
Marko Mikulicic 0:c0ecb8bf28eb 30545 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30546 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30547 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30548 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30549 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30550
Marko Mikulicic 0:c0ecb8bf28eb 30551 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30552 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30553 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30554
Marko Mikulicic 0:c0ecb8bf28eb 30555 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30556 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30557 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30558 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30559 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30560 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30561 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30562 }
Marko Mikulicic 0:c0ecb8bf28eb 30563 if (v7_is_truthy(v7, el)) {
Marko Mikulicic 0:c0ecb8bf28eb 30564 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30565 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30566 }
Marko Mikulicic 0:c0ecb8bf28eb 30567 }
Marko Mikulicic 0:c0ecb8bf28eb 30568 }
Marko Mikulicic 0:c0ecb8bf28eb 30569
Marko Mikulicic 0:c0ecb8bf28eb 30570 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30571
Marko Mikulicic 0:c0ecb8bf28eb 30572 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30573 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30574 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30575 }
Marko Mikulicic 0:c0ecb8bf28eb 30576
Marko Mikulicic 0:c0ecb8bf28eb 30577 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30578 V7_PRIVATE enum v7_err Array_filter(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30579 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30580 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30581 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30582 unsigned long len, i;
Marko Mikulicic 0:c0ecb8bf28eb 30583 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30584 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30585 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30586
Marko Mikulicic 0:c0ecb8bf28eb 30587 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30588 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30589 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30590 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30591 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30592 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30593 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30594
Marko Mikulicic 0:c0ecb8bf28eb 30595 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30596 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30597 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30598
Marko Mikulicic 0:c0ecb8bf28eb 30599 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30600 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30601 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30602 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30603 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30604 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30605 }
Marko Mikulicic 0:c0ecb8bf28eb 30606 if (v7_is_truthy(v7, el)) {
Marko Mikulicic 0:c0ecb8bf28eb 30607 rcode = v7_array_push_throwing(v7, *res, v, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30608 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30609 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30610 }
Marko Mikulicic 0:c0ecb8bf28eb 30611 }
Marko Mikulicic 0:c0ecb8bf28eb 30612 }
Marko Mikulicic 0:c0ecb8bf28eb 30613 }
Marko Mikulicic 0:c0ecb8bf28eb 30614
Marko Mikulicic 0:c0ecb8bf28eb 30615 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30616 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30617 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30618 }
Marko Mikulicic 0:c0ecb8bf28eb 30619
Marko Mikulicic 0:c0ecb8bf28eb 30620 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30621 V7_PRIVATE enum v7_err Array_concat(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30622 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30623 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30624 size_t i, j, len;
Marko Mikulicic 0:c0ecb8bf28eb 30625 val_t saved_args;
Marko Mikulicic 0:c0ecb8bf28eb 30626
Marko Mikulicic 0:c0ecb8bf28eb 30627 if (!v7_is_array(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30628 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30629 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30630 }
Marko Mikulicic 0:c0ecb8bf28eb 30631
Marko Mikulicic 0:c0ecb8bf28eb 30632 len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30633
Marko Mikulicic 0:c0ecb8bf28eb 30634 /*
Marko Mikulicic 0:c0ecb8bf28eb 30635 * reuse a_splice but override it's arguments. a_splice
Marko Mikulicic 0:c0ecb8bf28eb 30636 * internally uses a lot of helpers that fetch arguments
Marko Mikulicic 0:c0ecb8bf28eb 30637 * from the v7 context.
Marko Mikulicic 0:c0ecb8bf28eb 30638 * TODO(mkm): we need a better helper call another cfunction
Marko Mikulicic 0:c0ecb8bf28eb 30639 * from a cfunction.
Marko Mikulicic 0:c0ecb8bf28eb 30640 */
Marko Mikulicic 0:c0ecb8bf28eb 30641 saved_args = v7->vals.arguments;
Marko Mikulicic 0:c0ecb8bf28eb 30642 v7->vals.arguments = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 30643 rcode = a_splice(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 30644 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30645 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30646 }
Marko Mikulicic 0:c0ecb8bf28eb 30647 v7->vals.arguments = saved_args;
Marko Mikulicic 0:c0ecb8bf28eb 30648
Marko Mikulicic 0:c0ecb8bf28eb 30649 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30650 val_t a = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 30651 if (!v7_is_array(v7, a)) {
Marko Mikulicic 0:c0ecb8bf28eb 30652 rcode = v7_array_push_throwing(v7, *res, a, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30653 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30654 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30655 }
Marko Mikulicic 0:c0ecb8bf28eb 30656 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30657 size_t alen = v7_array_length(v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 30658 for (j = 0; j < alen; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 30659 rcode = v7_array_push_throwing(v7, *res, v7_array_get(v7, a, j), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30660 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30661 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30662 }
Marko Mikulicic 0:c0ecb8bf28eb 30663 }
Marko Mikulicic 0:c0ecb8bf28eb 30664 }
Marko Mikulicic 0:c0ecb8bf28eb 30665 }
Marko Mikulicic 0:c0ecb8bf28eb 30666
Marko Mikulicic 0:c0ecb8bf28eb 30667 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30668 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30669 }
Marko Mikulicic 0:c0ecb8bf28eb 30670
Marko Mikulicic 0:c0ecb8bf28eb 30671 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30672 V7_PRIVATE enum v7_err Array_isArray(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30673 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30674 *res = v7_mk_boolean(v7, v7_is_array(v7, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 30675 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30676 }
Marko Mikulicic 0:c0ecb8bf28eb 30677
Marko Mikulicic 0:c0ecb8bf28eb 30678 V7_PRIVATE void init_array(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 30679 val_t ctor = mk_cfunction_obj(v7, Array_ctor, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30680 val_t length = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30681
Marko Mikulicic 0:c0ecb8bf28eb 30682 v7_set(v7, ctor, "prototype", 9, v7->vals.array_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 30683 set_method(v7, ctor, "isArray", Array_isArray, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30684 v7_set(v7, v7->vals.global_object, "Array", 5, ctor);
Marko Mikulicic 0:c0ecb8bf28eb 30685 v7_def(v7, v7->vals.array_prototype, "constructor", ~0, _V7_DESC_HIDDEN(1),
Marko Mikulicic 0:c0ecb8bf28eb 30686 ctor);
Marko Mikulicic 0:c0ecb8bf28eb 30687 v7_set(v7, ctor, "name", 4, v7_mk_string(v7, "Array", ~0, 1));
Marko Mikulicic 0:c0ecb8bf28eb 30688
Marko Mikulicic 0:c0ecb8bf28eb 30689 set_method(v7, v7->vals.array_prototype, "concat", Array_concat, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30690 set_method(v7, v7->vals.array_prototype, "every", Array_every, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30691 set_method(v7, v7->vals.array_prototype, "filter", Array_filter, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30692 set_method(v7, v7->vals.array_prototype, "forEach", Array_forEach, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30693 set_method(v7, v7->vals.array_prototype, "join", Array_join, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30694 set_method(v7, v7->vals.array_prototype, "map", Array_map, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30695 set_method(v7, v7->vals.array_prototype, "push", Array_push, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30696 set_method(v7, v7->vals.array_prototype, "reverse", Array_reverse, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30697 set_method(v7, v7->vals.array_prototype, "slice", Array_slice, 2);
Marko Mikulicic 0:c0ecb8bf28eb 30698 set_method(v7, v7->vals.array_prototype, "some", Array_some, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30699 set_method(v7, v7->vals.array_prototype, "sort", Array_sort, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30700 set_method(v7, v7->vals.array_prototype, "splice", Array_splice, 2);
Marko Mikulicic 0:c0ecb8bf28eb 30701 set_method(v7, v7->vals.array_prototype, "toString", Array_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30702
Marko Mikulicic 0:c0ecb8bf28eb 30703 v7_array_set(v7, length, 0, v7_mk_cfunction(Array_get_length));
Marko Mikulicic 0:c0ecb8bf28eb 30704 v7_array_set(v7, length, 1, v7_mk_cfunction(Array_set_length));
Marko Mikulicic 0:c0ecb8bf28eb 30705 v7_def(v7, v7->vals.array_prototype, "length", 6,
Marko Mikulicic 0:c0ecb8bf28eb 30706 V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1) | V7_DESC_SETTER(1), length);
Marko Mikulicic 0:c0ecb8bf28eb 30707 }
Marko Mikulicic 0:c0ecb8bf28eb 30708
Marko Mikulicic 0:c0ecb8bf28eb 30709 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30710 }
Marko Mikulicic 0:c0ecb8bf28eb 30711 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30712 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 30713 #line 1 "v7/src/std_boolean.c"
Marko Mikulicic 0:c0ecb8bf28eb 30714 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30715 /*
Marko Mikulicic 0:c0ecb8bf28eb 30716 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 30717 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 30718 */
Marko Mikulicic 0:c0ecb8bf28eb 30719
Marko Mikulicic 0:c0ecb8bf28eb 30720 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30721 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30722 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30723 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30724 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30725 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30726 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30727 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30728 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30729
Marko Mikulicic 0:c0ecb8bf28eb 30730 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30731 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 30732 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30733
Marko Mikulicic 0:c0ecb8bf28eb 30734 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30735 V7_PRIVATE enum v7_err Boolean_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30736 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30737 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30738
Marko Mikulicic 0:c0ecb8bf28eb 30739 *res = to_boolean_v(v7, v7_arg(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 30740
Marko Mikulicic 0:c0ecb8bf28eb 30741 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 30742 /* called as "new Boolean(...)" */
Marko Mikulicic 0:c0ecb8bf28eb 30743 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 30744 get_object_struct(v7->vals.boolean_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 30745 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 30746
Marko Mikulicic 0:c0ecb8bf28eb 30747 /*
Marko Mikulicic 0:c0ecb8bf28eb 30748 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 30749 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 30750 */
Marko Mikulicic 0:c0ecb8bf28eb 30751 }
Marko Mikulicic 0:c0ecb8bf28eb 30752
Marko Mikulicic 0:c0ecb8bf28eb 30753 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30754 }
Marko Mikulicic 0:c0ecb8bf28eb 30755
Marko Mikulicic 0:c0ecb8bf28eb 30756 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30757 V7_PRIVATE enum v7_err Boolean_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30758 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30759 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30760 if (!v7_is_boolean(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30761 (v7_is_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30762 v7_get_proto(v7, this_obj) != v7->vals.boolean_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 30763 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 30764 "Boolean.valueOf called on non-boolean object");
Marko Mikulicic 0:c0ecb8bf28eb 30765 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30766 }
Marko Mikulicic 0:c0ecb8bf28eb 30767
Marko Mikulicic 0:c0ecb8bf28eb 30768 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 30769 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30770 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30771 }
Marko Mikulicic 0:c0ecb8bf28eb 30772
Marko Mikulicic 0:c0ecb8bf28eb 30773 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30774 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30775 }
Marko Mikulicic 0:c0ecb8bf28eb 30776
Marko Mikulicic 0:c0ecb8bf28eb 30777 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30778 V7_PRIVATE enum v7_err Boolean_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30779 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30780 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30781
Marko Mikulicic 0:c0ecb8bf28eb 30782 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 30783
Marko Mikulicic 0:c0ecb8bf28eb 30784 if (this_obj == v7->vals.boolean_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 30785 *res = v7_mk_string(v7, "false", 5, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30786 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30787 }
Marko Mikulicic 0:c0ecb8bf28eb 30788
Marko Mikulicic 0:c0ecb8bf28eb 30789 if (!v7_is_boolean(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30790 !(v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30791 is_prototype_of(v7, this_obj, v7->vals.boolean_prototype))) {
Marko Mikulicic 0:c0ecb8bf28eb 30792 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 30793 "Boolean.toString called on non-boolean object");
Marko Mikulicic 0:c0ecb8bf28eb 30794 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30795 }
Marko Mikulicic 0:c0ecb8bf28eb 30796
Marko Mikulicic 0:c0ecb8bf28eb 30797 rcode = obj_value_of(v7, this_obj, res);
Marko Mikulicic 0:c0ecb8bf28eb 30798 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30799 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30800 }
Marko Mikulicic 0:c0ecb8bf28eb 30801
Marko Mikulicic 0:c0ecb8bf28eb 30802 rcode = primitive_to_str(v7, *res, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30803 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30804 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30805 }
Marko Mikulicic 0:c0ecb8bf28eb 30806
Marko Mikulicic 0:c0ecb8bf28eb 30807 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30808 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30809 }
Marko Mikulicic 0:c0ecb8bf28eb 30810
Marko Mikulicic 0:c0ecb8bf28eb 30811 V7_PRIVATE void init_boolean(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 30812 val_t ctor = mk_cfunction_obj_with_proto(v7, Boolean_ctor, 1,
Marko Mikulicic 0:c0ecb8bf28eb 30813 v7->vals.boolean_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 30814 v7_set(v7, v7->vals.global_object, "Boolean", 7, ctor);
Marko Mikulicic 0:c0ecb8bf28eb 30815
Marko Mikulicic 0:c0ecb8bf28eb 30816 set_cfunc_prop(v7, v7->vals.boolean_prototype, "valueOf", Boolean_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 30817 set_cfunc_prop(v7, v7->vals.boolean_prototype, "toString", Boolean_toString);
Marko Mikulicic 0:c0ecb8bf28eb 30818 }
Marko Mikulicic 0:c0ecb8bf28eb 30819
Marko Mikulicic 0:c0ecb8bf28eb 30820 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30821 }
Marko Mikulicic 0:c0ecb8bf28eb 30822 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30823 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 30824 #line 1 "v7/src/std_math.c"
Marko Mikulicic 0:c0ecb8bf28eb 30825 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30826 /*
Marko Mikulicic 0:c0ecb8bf28eb 30827 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 30828 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 30829 */
Marko Mikulicic 0:c0ecb8bf28eb 30830
Marko Mikulicic 0:c0ecb8bf28eb 30831 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30832 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30833 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30834 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30835
Marko Mikulicic 0:c0ecb8bf28eb 30836 #if V7_ENABLE__Math
Marko Mikulicic 0:c0ecb8bf28eb 30837
Marko Mikulicic 0:c0ecb8bf28eb 30838 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30839 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 30840 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30841
Marko Mikulicic 0:c0ecb8bf28eb 30842 #ifdef __WATCOM__
Marko Mikulicic 0:c0ecb8bf28eb 30843 int matherr(struct _exception *exc) {
Marko Mikulicic 0:c0ecb8bf28eb 30844 if (exc->type == DOMAIN) {
Marko Mikulicic 0:c0ecb8bf28eb 30845 exc->retval = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30846 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 30847 }
Marko Mikulicic 0:c0ecb8bf28eb 30848 }
Marko Mikulicic 0:c0ecb8bf28eb 30849 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30850
Marko Mikulicic 0:c0ecb8bf28eb 30851 #if V7_ENABLE__Math__abs || V7_ENABLE__Math__acos || V7_ENABLE__Math__asin || \
Marko Mikulicic 0:c0ecb8bf28eb 30852 V7_ENABLE__Math__atan || V7_ENABLE__Math__ceil || V7_ENABLE__Math__cos || \
Marko Mikulicic 0:c0ecb8bf28eb 30853 V7_ENABLE__Math__exp || V7_ENABLE__Math__floor || V7_ENABLE__Math__log || \
Marko Mikulicic 0:c0ecb8bf28eb 30854 V7_ENABLE__Math__round || V7_ENABLE__Math__sin || V7_ENABLE__Math__sqrt || \
Marko Mikulicic 0:c0ecb8bf28eb 30855 V7_ENABLE__Math__tan
Marko Mikulicic 0:c0ecb8bf28eb 30856 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30857 static enum v7_err m_one_arg(struct v7 *v7, double (*f)(double), val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30858 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30859 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30860 double d0 = v7_get_double(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30861 #ifdef V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 30862 if (isnan(d0)) {
Marko Mikulicic 0:c0ecb8bf28eb 30863 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30864 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30865 }
Marko Mikulicic 0:c0ecb8bf28eb 30866 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30867 *res = v7_mk_number(v7, f(d0));
Marko Mikulicic 0:c0ecb8bf28eb 30868 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30869
Marko Mikulicic 0:c0ecb8bf28eb 30870 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30871 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30872 }
Marko Mikulicic 0:c0ecb8bf28eb 30873 #endif /* V7_ENABLE__Math__* */
Marko Mikulicic 0:c0ecb8bf28eb 30874
Marko Mikulicic 0:c0ecb8bf28eb 30875 #if V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2
Marko Mikulicic 0:c0ecb8bf28eb 30876 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30877 static enum v7_err m_two_arg(struct v7 *v7, double (*f)(double, double),
Marko Mikulicic 0:c0ecb8bf28eb 30878 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30879 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30880 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30881 val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30882 double d0 = v7_get_double(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30883 double d1 = v7_get_double(v7, arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30884 #ifdef V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 30885 /* pow(NaN,0) == 1, doesn't fix atan2, but who cares */
Marko Mikulicic 0:c0ecb8bf28eb 30886 if (isnan(d1)) {
Marko Mikulicic 0:c0ecb8bf28eb 30887 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30888 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30889 }
Marko Mikulicic 0:c0ecb8bf28eb 30890 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30891 *res = v7_mk_number(v7, f(d0, d1));
Marko Mikulicic 0:c0ecb8bf28eb 30892 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30893
Marko Mikulicic 0:c0ecb8bf28eb 30894 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30895 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30896 }
Marko Mikulicic 0:c0ecb8bf28eb 30897 #endif /* V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2 */
Marko Mikulicic 0:c0ecb8bf28eb 30898
Marko Mikulicic 0:c0ecb8bf28eb 30899 #define DEFINE_WRAPPER(name, func) \
Marko Mikulicic 0:c0ecb8bf28eb 30900 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 30901 V7_PRIVATE enum v7_err Math_##name(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 30902 return func(v7, name, res); \
Marko Mikulicic 0:c0ecb8bf28eb 30903 }
Marko Mikulicic 0:c0ecb8bf28eb 30904
Marko Mikulicic 0:c0ecb8bf28eb 30905 /* Visual studio 2012+ has round() */
Marko Mikulicic 0:c0ecb8bf28eb 30906 #if V7_ENABLE__Math__round && \
Marko Mikulicic 0:c0ecb8bf28eb 30907 ((defined(V7_WINDOWS) && _MSC_VER < 1700) || defined(__WATCOM__))
Marko Mikulicic 0:c0ecb8bf28eb 30908 static double round(double n) {
Marko Mikulicic 0:c0ecb8bf28eb 30909 return n;
Marko Mikulicic 0:c0ecb8bf28eb 30910 }
Marko Mikulicic 0:c0ecb8bf28eb 30911 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30912
Marko Mikulicic 0:c0ecb8bf28eb 30913 #if V7_ENABLE__Math__abs
Marko Mikulicic 0:c0ecb8bf28eb 30914 DEFINE_WRAPPER(fabs, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30915 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30916 #if V7_ENABLE__Math__acos
Marko Mikulicic 0:c0ecb8bf28eb 30917 DEFINE_WRAPPER(acos, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30918 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30919 #if V7_ENABLE__Math__asin
Marko Mikulicic 0:c0ecb8bf28eb 30920 DEFINE_WRAPPER(asin, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30921 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30922 #if V7_ENABLE__Math__atan
Marko Mikulicic 0:c0ecb8bf28eb 30923 DEFINE_WRAPPER(atan, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30924 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30925 #if V7_ENABLE__Math__atan2
Marko Mikulicic 0:c0ecb8bf28eb 30926 DEFINE_WRAPPER(atan2, m_two_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30927 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30928 #if V7_ENABLE__Math__ceil
Marko Mikulicic 0:c0ecb8bf28eb 30929 DEFINE_WRAPPER(ceil, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30930 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30931 #if V7_ENABLE__Math__cos
Marko Mikulicic 0:c0ecb8bf28eb 30932 DEFINE_WRAPPER(cos, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30933 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30934 #if V7_ENABLE__Math__exp
Marko Mikulicic 0:c0ecb8bf28eb 30935 DEFINE_WRAPPER(exp, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30936 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30937 #if V7_ENABLE__Math__floor
Marko Mikulicic 0:c0ecb8bf28eb 30938 DEFINE_WRAPPER(floor, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30939 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30940 #if V7_ENABLE__Math__log
Marko Mikulicic 0:c0ecb8bf28eb 30941 DEFINE_WRAPPER(log, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30942 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30943 #if V7_ENABLE__Math__pow
Marko Mikulicic 0:c0ecb8bf28eb 30944 DEFINE_WRAPPER(pow, m_two_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30945 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30946 #if V7_ENABLE__Math__round
Marko Mikulicic 0:c0ecb8bf28eb 30947 DEFINE_WRAPPER(round, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30948 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30949 #if V7_ENABLE__Math__sin
Marko Mikulicic 0:c0ecb8bf28eb 30950 DEFINE_WRAPPER(sin, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30951 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30952 #if V7_ENABLE__Math__sqrt
Marko Mikulicic 0:c0ecb8bf28eb 30953 DEFINE_WRAPPER(sqrt, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30954 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30955 #if V7_ENABLE__Math__tan
Marko Mikulicic 0:c0ecb8bf28eb 30956 DEFINE_WRAPPER(tan, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30957 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30958
Marko Mikulicic 0:c0ecb8bf28eb 30959 #if V7_ENABLE__Math__random
Marko Mikulicic 0:c0ecb8bf28eb 30960 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30961 V7_PRIVATE enum v7_err Math_random(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30962 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 30963 *res = v7_mk_number(v7, (double) rand() / RAND_MAX);
Marko Mikulicic 0:c0ecb8bf28eb 30964 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30965 }
Marko Mikulicic 0:c0ecb8bf28eb 30966 #endif /* V7_ENABLE__Math__random */
Marko Mikulicic 0:c0ecb8bf28eb 30967
Marko Mikulicic 0:c0ecb8bf28eb 30968 #if V7_ENABLE__Math__min || V7_ENABLE__Math__max
Marko Mikulicic 0:c0ecb8bf28eb 30969 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30970 static enum v7_err min_max(struct v7 *v7, int is_min, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30971 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30972 double dres = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30973 int i, len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30974
Marko Mikulicic 0:c0ecb8bf28eb 30975 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30976 double v = v7_get_double(v7, v7_arg(v7, i));
Marko Mikulicic 0:c0ecb8bf28eb 30977 if (isnan(dres) || (is_min && v < dres) || (!is_min && v > dres)) {
Marko Mikulicic 0:c0ecb8bf28eb 30978 dres = v;
Marko Mikulicic 0:c0ecb8bf28eb 30979 }
Marko Mikulicic 0:c0ecb8bf28eb 30980 }
Marko Mikulicic 0:c0ecb8bf28eb 30981
Marko Mikulicic 0:c0ecb8bf28eb 30982 *res = v7_mk_number(v7, dres);
Marko Mikulicic 0:c0ecb8bf28eb 30983
Marko Mikulicic 0:c0ecb8bf28eb 30984 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30985 }
Marko Mikulicic 0:c0ecb8bf28eb 30986 #endif /* V7_ENABLE__Math__min || V7_ENABLE__Math__max */
Marko Mikulicic 0:c0ecb8bf28eb 30987
Marko Mikulicic 0:c0ecb8bf28eb 30988 #if V7_ENABLE__Math__min
Marko Mikulicic 0:c0ecb8bf28eb 30989 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30990 V7_PRIVATE enum v7_err Math_min(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30991 return min_max(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 30992 }
Marko Mikulicic 0:c0ecb8bf28eb 30993 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30994
Marko Mikulicic 0:c0ecb8bf28eb 30995 #if V7_ENABLE__Math__max
Marko Mikulicic 0:c0ecb8bf28eb 30996 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30997 V7_PRIVATE enum v7_err Math_max(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30998 return min_max(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 30999 }
Marko Mikulicic 0:c0ecb8bf28eb 31000 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31001
Marko Mikulicic 0:c0ecb8bf28eb 31002 V7_PRIVATE void init_math(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 31003 val_t math = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31004
Marko Mikulicic 0:c0ecb8bf28eb 31005 #if V7_ENABLE__Math__abs
Marko Mikulicic 0:c0ecb8bf28eb 31006 set_cfunc_prop(v7, math, "abs", Math_fabs);
Marko Mikulicic 0:c0ecb8bf28eb 31007 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31008 #if V7_ENABLE__Math__acos
Marko Mikulicic 0:c0ecb8bf28eb 31009 set_cfunc_prop(v7, math, "acos", Math_acos);
Marko Mikulicic 0:c0ecb8bf28eb 31010 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31011 #if V7_ENABLE__Math__asin
Marko Mikulicic 0:c0ecb8bf28eb 31012 set_cfunc_prop(v7, math, "asin", Math_asin);
Marko Mikulicic 0:c0ecb8bf28eb 31013 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31014 #if V7_ENABLE__Math__atan
Marko Mikulicic 0:c0ecb8bf28eb 31015 set_cfunc_prop(v7, math, "atan", Math_atan);
Marko Mikulicic 0:c0ecb8bf28eb 31016 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31017 #if V7_ENABLE__Math__atan2
Marko Mikulicic 0:c0ecb8bf28eb 31018 set_cfunc_prop(v7, math, "atan2", Math_atan2);
Marko Mikulicic 0:c0ecb8bf28eb 31019 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31020 #if V7_ENABLE__Math__ceil
Marko Mikulicic 0:c0ecb8bf28eb 31021 set_cfunc_prop(v7, math, "ceil", Math_ceil);
Marko Mikulicic 0:c0ecb8bf28eb 31022 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31023 #if V7_ENABLE__Math__cos
Marko Mikulicic 0:c0ecb8bf28eb 31024 set_cfunc_prop(v7, math, "cos", Math_cos);
Marko Mikulicic 0:c0ecb8bf28eb 31025 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31026 #if V7_ENABLE__Math__exp
Marko Mikulicic 0:c0ecb8bf28eb 31027 set_cfunc_prop(v7, math, "exp", Math_exp);
Marko Mikulicic 0:c0ecb8bf28eb 31028 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31029 #if V7_ENABLE__Math__floor
Marko Mikulicic 0:c0ecb8bf28eb 31030 set_cfunc_prop(v7, math, "floor", Math_floor);
Marko Mikulicic 0:c0ecb8bf28eb 31031 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31032 #if V7_ENABLE__Math__log
Marko Mikulicic 0:c0ecb8bf28eb 31033 set_cfunc_prop(v7, math, "log", Math_log);
Marko Mikulicic 0:c0ecb8bf28eb 31034 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31035 #if V7_ENABLE__Math__max
Marko Mikulicic 0:c0ecb8bf28eb 31036 set_cfunc_prop(v7, math, "max", Math_max);
Marko Mikulicic 0:c0ecb8bf28eb 31037 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31038 #if V7_ENABLE__Math__min
Marko Mikulicic 0:c0ecb8bf28eb 31039 set_cfunc_prop(v7, math, "min", Math_min);
Marko Mikulicic 0:c0ecb8bf28eb 31040 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31041 #if V7_ENABLE__Math__pow
Marko Mikulicic 0:c0ecb8bf28eb 31042 set_cfunc_prop(v7, math, "pow", Math_pow);
Marko Mikulicic 0:c0ecb8bf28eb 31043 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31044 #if V7_ENABLE__Math__random
Marko Mikulicic 0:c0ecb8bf28eb 31045 /* Incorporate our pointer into the RNG.
Marko Mikulicic 0:c0ecb8bf28eb 31046 * If srand() has not been called before, this will provide some randomness.
Marko Mikulicic 0:c0ecb8bf28eb 31047 * If it has, it will hopefully not make things worse.
Marko Mikulicic 0:c0ecb8bf28eb 31048 */
Marko Mikulicic 0:c0ecb8bf28eb 31049 srand(rand() ^ ((uintptr_t) v7));
Marko Mikulicic 0:c0ecb8bf28eb 31050 set_cfunc_prop(v7, math, "random", Math_random);
Marko Mikulicic 0:c0ecb8bf28eb 31051 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31052 #if V7_ENABLE__Math__round
Marko Mikulicic 0:c0ecb8bf28eb 31053 set_cfunc_prop(v7, math, "round", Math_round);
Marko Mikulicic 0:c0ecb8bf28eb 31054 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31055 #if V7_ENABLE__Math__sin
Marko Mikulicic 0:c0ecb8bf28eb 31056 set_cfunc_prop(v7, math, "sin", Math_sin);
Marko Mikulicic 0:c0ecb8bf28eb 31057 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31058 #if V7_ENABLE__Math__sqrt
Marko Mikulicic 0:c0ecb8bf28eb 31059 set_cfunc_prop(v7, math, "sqrt", Math_sqrt);
Marko Mikulicic 0:c0ecb8bf28eb 31060 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31061 #if V7_ENABLE__Math__tan
Marko Mikulicic 0:c0ecb8bf28eb 31062 set_cfunc_prop(v7, math, "tan", Math_tan);
Marko Mikulicic 0:c0ecb8bf28eb 31063 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31064
Marko Mikulicic 0:c0ecb8bf28eb 31065 #if V7_ENABLE__Math__constants
Marko Mikulicic 0:c0ecb8bf28eb 31066 v7_set(v7, math, "E", 1, v7_mk_number(v7, M_E));
Marko Mikulicic 0:c0ecb8bf28eb 31067 v7_set(v7, math, "PI", 2, v7_mk_number(v7, M_PI));
Marko Mikulicic 0:c0ecb8bf28eb 31068 v7_set(v7, math, "LN2", 3, v7_mk_number(v7, M_LN2));
Marko Mikulicic 0:c0ecb8bf28eb 31069 v7_set(v7, math, "LN10", 4, v7_mk_number(v7, M_LN10));
Marko Mikulicic 0:c0ecb8bf28eb 31070 v7_set(v7, math, "LOG2E", 5, v7_mk_number(v7, M_LOG2E));
Marko Mikulicic 0:c0ecb8bf28eb 31071 v7_set(v7, math, "LOG10E", 6, v7_mk_number(v7, M_LOG10E));
Marko Mikulicic 0:c0ecb8bf28eb 31072 v7_set(v7, math, "SQRT1_2", 7, v7_mk_number(v7, M_SQRT1_2));
Marko Mikulicic 0:c0ecb8bf28eb 31073 v7_set(v7, math, "SQRT2", 5, v7_mk_number(v7, M_SQRT2));
Marko Mikulicic 0:c0ecb8bf28eb 31074 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31075
Marko Mikulicic 0:c0ecb8bf28eb 31076 v7_set(v7, v7->vals.global_object, "Math", 4, math);
Marko Mikulicic 0:c0ecb8bf28eb 31077 }
Marko Mikulicic 0:c0ecb8bf28eb 31078
Marko Mikulicic 0:c0ecb8bf28eb 31079 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 31080 }
Marko Mikulicic 0:c0ecb8bf28eb 31081 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 31082
Marko Mikulicic 0:c0ecb8bf28eb 31083 #endif /* V7_ENABLE__Math */
Marko Mikulicic 0:c0ecb8bf28eb 31084 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 31085 #line 1 "v7/src/std_string.c"
Marko Mikulicic 0:c0ecb8bf28eb 31086 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31087 /*
Marko Mikulicic 0:c0ecb8bf28eb 31088 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 31089 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 31090 */
Marko Mikulicic 0:c0ecb8bf28eb 31091
Marko Mikulicic 0:c0ecb8bf28eb 31092 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31093 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31094 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31095 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31096 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31097 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31098 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31099 /* Amalgamated: #include "v7/src/std_regex.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31100 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31101 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31102 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31103 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31104 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31105 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31106 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31107
Marko Mikulicic 0:c0ecb8bf28eb 31108 /* Substring implementations: RegExp-based and String-based {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 31109
Marko Mikulicic 0:c0ecb8bf28eb 31110 /*
Marko Mikulicic 0:c0ecb8bf28eb 31111 * Substring context: currently, used in Str_split() only, but will probably
Marko Mikulicic 0:c0ecb8bf28eb 31112 * be used in Str_replace() and other functions as well.
Marko Mikulicic 0:c0ecb8bf28eb 31113 *
Marko Mikulicic 0:c0ecb8bf28eb 31114 * Needed to provide different implementation for RegExp or String arguments,
Marko Mikulicic 0:c0ecb8bf28eb 31115 * keeping common parts reusable.
Marko Mikulicic 0:c0ecb8bf28eb 31116 */
Marko Mikulicic 0:c0ecb8bf28eb 31117 struct _str_split_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 31118 /* implementation-specific data */
Marko Mikulicic 0:c0ecb8bf28eb 31119 union {
Marko Mikulicic 0:c0ecb8bf28eb 31120 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31121 struct {
Marko Mikulicic 0:c0ecb8bf28eb 31122 struct slre_prog *prog;
Marko Mikulicic 0:c0ecb8bf28eb 31123 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 31124 } regexp;
Marko Mikulicic 0:c0ecb8bf28eb 31125 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31126
Marko Mikulicic 0:c0ecb8bf28eb 31127 struct {
Marko Mikulicic 0:c0ecb8bf28eb 31128 val_t sep;
Marko Mikulicic 0:c0ecb8bf28eb 31129 } string;
Marko Mikulicic 0:c0ecb8bf28eb 31130 } impl;
Marko Mikulicic 0:c0ecb8bf28eb 31131
Marko Mikulicic 0:c0ecb8bf28eb 31132 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 31133
Marko Mikulicic 0:c0ecb8bf28eb 31134 /* start and end of previous match (set by `p_exec()`) */
Marko Mikulicic 0:c0ecb8bf28eb 31135 const char *match_start;
Marko Mikulicic 0:c0ecb8bf28eb 31136 const char *match_end;
Marko Mikulicic 0:c0ecb8bf28eb 31137
Marko Mikulicic 0:c0ecb8bf28eb 31138 /* pointers to implementation functions */
Marko Mikulicic 0:c0ecb8bf28eb 31139
Marko Mikulicic 0:c0ecb8bf28eb 31140 /*
Marko Mikulicic 0:c0ecb8bf28eb 31141 * Initialize context
Marko Mikulicic 0:c0ecb8bf28eb 31142 */
Marko Mikulicic 0:c0ecb8bf28eb 31143 void (*p_init)(struct _str_split_ctx *ctx, struct v7 *v7, val_t sep);
Marko Mikulicic 0:c0ecb8bf28eb 31144
Marko Mikulicic 0:c0ecb8bf28eb 31145 /*
Marko Mikulicic 0:c0ecb8bf28eb 31146 * Look for the next match, set `match_start` and `match_end` to appropriate
Marko Mikulicic 0:c0ecb8bf28eb 31147 * values.
Marko Mikulicic 0:c0ecb8bf28eb 31148 *
Marko Mikulicic 0:c0ecb8bf28eb 31149 * Returns 0 if match found, 1 otherwise (in accordance with `slre_exec()`)
Marko Mikulicic 0:c0ecb8bf28eb 31150 */
Marko Mikulicic 0:c0ecb8bf28eb 31151 int (*p_exec)(struct _str_split_ctx *ctx, const char *start, const char *end);
Marko Mikulicic 0:c0ecb8bf28eb 31152
Marko Mikulicic 0:c0ecb8bf28eb 31153 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31154 /*
Marko Mikulicic 0:c0ecb8bf28eb 31155 * Add captured data to resulting array (for RegExp-based implementation only)
Marko Mikulicic 0:c0ecb8bf28eb 31156 *
Marko Mikulicic 0:c0ecb8bf28eb 31157 * Returns updated `elem` value
Marko Mikulicic 0:c0ecb8bf28eb 31158 */
Marko Mikulicic 0:c0ecb8bf28eb 31159 long (*p_add_caps)(struct _str_split_ctx *ctx, val_t res, long elem,
Marko Mikulicic 0:c0ecb8bf28eb 31160 long limit);
Marko Mikulicic 0:c0ecb8bf28eb 31161 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31162 };
Marko Mikulicic 0:c0ecb8bf28eb 31163
Marko Mikulicic 0:c0ecb8bf28eb 31164 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31165 /* RegExp-based implementation of `p_init` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31166 static void subs_regexp_init(struct _str_split_ctx *ctx, struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 31167 val_t sep) {
Marko Mikulicic 0:c0ecb8bf28eb 31168 ctx->v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 31169 ctx->impl.regexp.prog = v7_get_regexp_struct(v7, sep)->compiled_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 31170 }
Marko Mikulicic 0:c0ecb8bf28eb 31171
Marko Mikulicic 0:c0ecb8bf28eb 31172 /* RegExp-based implementation of `p_exec` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31173 static int subs_regexp_exec(struct _str_split_ctx *ctx, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 31174 const char *end) {
Marko Mikulicic 0:c0ecb8bf28eb 31175 int ret =
Marko Mikulicic 0:c0ecb8bf28eb 31176 slre_exec(ctx->impl.regexp.prog, 0, start, end, &ctx->impl.regexp.loot);
Marko Mikulicic 0:c0ecb8bf28eb 31177
Marko Mikulicic 0:c0ecb8bf28eb 31178 ctx->match_start = ctx->impl.regexp.loot.caps[0].start;
Marko Mikulicic 0:c0ecb8bf28eb 31179 ctx->match_end = ctx->impl.regexp.loot.caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 31180
Marko Mikulicic 0:c0ecb8bf28eb 31181 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 31182 }
Marko Mikulicic 0:c0ecb8bf28eb 31183
Marko Mikulicic 0:c0ecb8bf28eb 31184 /* RegExp-based implementation of `p_add_caps` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31185 static long subs_regexp_split_add_caps(struct _str_split_ctx *ctx, val_t res,
Marko Mikulicic 0:c0ecb8bf28eb 31186 long elem, long limit) {
Marko Mikulicic 0:c0ecb8bf28eb 31187 int i;
Marko Mikulicic 0:c0ecb8bf28eb 31188 for (i = 1; i < ctx->impl.regexp.loot.num_captures && elem < limit; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31189 size_t cap_len =
Marko Mikulicic 0:c0ecb8bf28eb 31190 ctx->impl.regexp.loot.caps[i].end - ctx->impl.regexp.loot.caps[i].start;
Marko Mikulicic 0:c0ecb8bf28eb 31191 v7_array_push(
Marko Mikulicic 0:c0ecb8bf28eb 31192 ctx->v7, res,
Marko Mikulicic 0:c0ecb8bf28eb 31193 (ctx->impl.regexp.loot.caps[i].start != NULL)
Marko Mikulicic 0:c0ecb8bf28eb 31194 ? v7_mk_string(ctx->v7, ctx->impl.regexp.loot.caps[i].start,
Marko Mikulicic 0:c0ecb8bf28eb 31195 cap_len, 1)
Marko Mikulicic 0:c0ecb8bf28eb 31196 : V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 31197 elem++;
Marko Mikulicic 0:c0ecb8bf28eb 31198 }
Marko Mikulicic 0:c0ecb8bf28eb 31199 return elem;
Marko Mikulicic 0:c0ecb8bf28eb 31200 }
Marko Mikulicic 0:c0ecb8bf28eb 31201 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31202
Marko Mikulicic 0:c0ecb8bf28eb 31203 /* String-based implementation of `p_init` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31204 static void subs_string_init(struct _str_split_ctx *ctx, struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 31205 val_t sep) {
Marko Mikulicic 0:c0ecb8bf28eb 31206 ctx->v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 31207 ctx->impl.string.sep = sep;
Marko Mikulicic 0:c0ecb8bf28eb 31208 }
Marko Mikulicic 0:c0ecb8bf28eb 31209
Marko Mikulicic 0:c0ecb8bf28eb 31210 /* String-based implementation of `p_exec` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31211 static int subs_string_exec(struct _str_split_ctx *ctx, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 31212 const char *end) {
Marko Mikulicic 0:c0ecb8bf28eb 31213 int ret = 1;
Marko Mikulicic 0:c0ecb8bf28eb 31214 size_t sep_len;
Marko Mikulicic 0:c0ecb8bf28eb 31215 const char *psep = v7_get_string(ctx->v7, &ctx->impl.string.sep, &sep_len);
Marko Mikulicic 0:c0ecb8bf28eb 31216
Marko Mikulicic 0:c0ecb8bf28eb 31217 if (sep_len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31218 /* separator is an empty string: match empty string */
Marko Mikulicic 0:c0ecb8bf28eb 31219 ctx->match_start = start;
Marko Mikulicic 0:c0ecb8bf28eb 31220 ctx->match_end = start;
Marko Mikulicic 0:c0ecb8bf28eb 31221 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31222 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31223 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 31224 for (i = 0; start <= (end - sep_len); ++i, start = utfnshift(start, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 31225 if (memcmp(start, psep, sep_len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31226 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31227 ctx->match_start = start;
Marko Mikulicic 0:c0ecb8bf28eb 31228 ctx->match_end = start + sep_len;
Marko Mikulicic 0:c0ecb8bf28eb 31229 break;
Marko Mikulicic 0:c0ecb8bf28eb 31230 }
Marko Mikulicic 0:c0ecb8bf28eb 31231 }
Marko Mikulicic 0:c0ecb8bf28eb 31232 }
Marko Mikulicic 0:c0ecb8bf28eb 31233
Marko Mikulicic 0:c0ecb8bf28eb 31234 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 31235 }
Marko Mikulicic 0:c0ecb8bf28eb 31236
Marko Mikulicic 0:c0ecb8bf28eb 31237 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31238 /* String-based implementation of `p_add_caps` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31239 static long subs_string_split_add_caps(struct _str_split_ctx *ctx, val_t res,
Marko Mikulicic 0:c0ecb8bf28eb 31240 long elem, long limit) {
Marko Mikulicic 0:c0ecb8bf28eb 31241 /* this is a stub function */
Marko Mikulicic 0:c0ecb8bf28eb 31242 (void) ctx;
Marko Mikulicic 0:c0ecb8bf28eb 31243 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 31244 (void) limit;
Marko Mikulicic 0:c0ecb8bf28eb 31245 return elem;
Marko Mikulicic 0:c0ecb8bf28eb 31246 }
Marko Mikulicic 0:c0ecb8bf28eb 31247 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31248
Marko Mikulicic 0:c0ecb8bf28eb 31249 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 31250
Marko Mikulicic 0:c0ecb8bf28eb 31251 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31252 V7_PRIVATE enum v7_err String_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31253 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31254 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31255 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 31256
Marko Mikulicic 0:c0ecb8bf28eb 31257 *res = arg0;
Marko Mikulicic 0:c0ecb8bf28eb 31258
Marko Mikulicic 0:c0ecb8bf28eb 31259 if (v7_argc(v7) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31260 *res = v7_mk_string(v7, NULL, 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31261 } else if (!v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 31262 rcode = to_string(v7, arg0, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31263 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31264 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31265 }
Marko Mikulicic 0:c0ecb8bf28eb 31266 }
Marko Mikulicic 0:c0ecb8bf28eb 31267
Marko Mikulicic 0:c0ecb8bf28eb 31268 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 31269 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 31270 get_object_struct(v7->vals.string_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 31271 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 31272 /*
Marko Mikulicic 0:c0ecb8bf28eb 31273 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 31274 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 31275 */
Marko Mikulicic 0:c0ecb8bf28eb 31276 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31277 }
Marko Mikulicic 0:c0ecb8bf28eb 31278
Marko Mikulicic 0:c0ecb8bf28eb 31279 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31280 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31281 }
Marko Mikulicic 0:c0ecb8bf28eb 31282
Marko Mikulicic 0:c0ecb8bf28eb 31283 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31284 V7_PRIVATE enum v7_err Str_fromCharCode(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31285 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31286 int i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31287
Marko Mikulicic 0:c0ecb8bf28eb 31288 *res = v7_mk_string(v7, "", 0, 1); /* Empty string */
Marko Mikulicic 0:c0ecb8bf28eb 31289
Marko Mikulicic 0:c0ecb8bf28eb 31290 for (i = 0; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31291 char buf[10];
Marko Mikulicic 0:c0ecb8bf28eb 31292 val_t arg = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 31293 double d = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 31294 Rune r = (Rune)((int32_t)(isnan(d) || isinf(d) ? 0 : d) & 0xffff);
Marko Mikulicic 0:c0ecb8bf28eb 31295 int n = runetochar(buf, &r);
Marko Mikulicic 0:c0ecb8bf28eb 31296 val_t s = v7_mk_string(v7, buf, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31297 *res = s_concat(v7, *res, s);
Marko Mikulicic 0:c0ecb8bf28eb 31298 }
Marko Mikulicic 0:c0ecb8bf28eb 31299
Marko Mikulicic 0:c0ecb8bf28eb 31300 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31301 }
Marko Mikulicic 0:c0ecb8bf28eb 31302
Marko Mikulicic 0:c0ecb8bf28eb 31303 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31304 static enum v7_err s_charCodeAt(struct v7 *v7, double *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31305 return v7_char_code_at(v7, v7_get_this(v7), v7_arg(v7, 0), res);
Marko Mikulicic 0:c0ecb8bf28eb 31306 }
Marko Mikulicic 0:c0ecb8bf28eb 31307
Marko Mikulicic 0:c0ecb8bf28eb 31308 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31309 V7_PRIVATE enum v7_err Str_charCodeAt(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31310 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31311 double dnum = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31312
Marko Mikulicic 0:c0ecb8bf28eb 31313 rcode = s_charCodeAt(v7, &dnum);
Marko Mikulicic 0:c0ecb8bf28eb 31314 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31315 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31316 }
Marko Mikulicic 0:c0ecb8bf28eb 31317
Marko Mikulicic 0:c0ecb8bf28eb 31318 *res = v7_mk_number(v7, dnum);
Marko Mikulicic 0:c0ecb8bf28eb 31319
Marko Mikulicic 0:c0ecb8bf28eb 31320 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31321 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31322 }
Marko Mikulicic 0:c0ecb8bf28eb 31323
Marko Mikulicic 0:c0ecb8bf28eb 31324 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31325 V7_PRIVATE enum v7_err Str_charAt(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31326 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31327 double code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31328 char buf[10] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 31329 int len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31330
Marko Mikulicic 0:c0ecb8bf28eb 31331 rcode = s_charCodeAt(v7, &code);
Marko Mikulicic 0:c0ecb8bf28eb 31332 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31333 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31334 }
Marko Mikulicic 0:c0ecb8bf28eb 31335
Marko Mikulicic 0:c0ecb8bf28eb 31336 if (!isnan(code)) {
Marko Mikulicic 0:c0ecb8bf28eb 31337 Rune r = (Rune) code;
Marko Mikulicic 0:c0ecb8bf28eb 31338 len = runetochar(buf, &r);
Marko Mikulicic 0:c0ecb8bf28eb 31339 }
Marko Mikulicic 0:c0ecb8bf28eb 31340 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31341
Marko Mikulicic 0:c0ecb8bf28eb 31342 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31343 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31344 }
Marko Mikulicic 0:c0ecb8bf28eb 31345
Marko Mikulicic 0:c0ecb8bf28eb 31346 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31347 V7_PRIVATE enum v7_err Str_concat(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31348 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31349 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31350 int i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31351
Marko Mikulicic 0:c0ecb8bf28eb 31352 rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31353 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31354 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31355 }
Marko Mikulicic 0:c0ecb8bf28eb 31356
Marko Mikulicic 0:c0ecb8bf28eb 31357 for (i = 0; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31358 val_t str = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31359
Marko Mikulicic 0:c0ecb8bf28eb 31360 rcode = to_string(v7, v7_arg(v7, i), &str, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31361 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31362 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31363 }
Marko Mikulicic 0:c0ecb8bf28eb 31364
Marko Mikulicic 0:c0ecb8bf28eb 31365 *res = s_concat(v7, *res, str);
Marko Mikulicic 0:c0ecb8bf28eb 31366 }
Marko Mikulicic 0:c0ecb8bf28eb 31367
Marko Mikulicic 0:c0ecb8bf28eb 31368 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31369 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31370 }
Marko Mikulicic 0:c0ecb8bf28eb 31371
Marko Mikulicic 0:c0ecb8bf28eb 31372 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31373 static enum v7_err s_index_of(struct v7 *v7, int last, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31374 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31375 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31376 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 31377 size_t fromIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31378 double dres = -1;
Marko Mikulicic 0:c0ecb8bf28eb 31379
Marko Mikulicic 0:c0ecb8bf28eb 31380 if (!v7_is_undefined(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 31381 const char *p1, *p2, *end;
Marko Mikulicic 0:c0ecb8bf28eb 31382 size_t i, len1, len2, bytecnt1, bytecnt2;
Marko Mikulicic 0:c0ecb8bf28eb 31383 val_t sub = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31384
Marko Mikulicic 0:c0ecb8bf28eb 31385 rcode = to_string(v7, arg0, &sub, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31386 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31387 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31388 }
Marko Mikulicic 0:c0ecb8bf28eb 31389
Marko Mikulicic 0:c0ecb8bf28eb 31390 rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31391 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31392 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31393 }
Marko Mikulicic 0:c0ecb8bf28eb 31394
Marko Mikulicic 0:c0ecb8bf28eb 31395 p1 = v7_get_string(v7, &this_obj, &bytecnt1);
Marko Mikulicic 0:c0ecb8bf28eb 31396 p2 = v7_get_string(v7, &sub, &bytecnt2);
Marko Mikulicic 0:c0ecb8bf28eb 31397
Marko Mikulicic 0:c0ecb8bf28eb 31398 if (bytecnt2 <= bytecnt1) {
Marko Mikulicic 0:c0ecb8bf28eb 31399 end = p1 + bytecnt1;
Marko Mikulicic 0:c0ecb8bf28eb 31400 len1 = utfnlen(p1, bytecnt1);
Marko Mikulicic 0:c0ecb8bf28eb 31401 len2 = utfnlen(p2, bytecnt2);
Marko Mikulicic 0:c0ecb8bf28eb 31402
Marko Mikulicic 0:c0ecb8bf28eb 31403 if (v7_argc(v7) > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 31404 /* `fromIndex` was provided. Normalize it */
Marko Mikulicic 0:c0ecb8bf28eb 31405 double d = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31406 {
Marko Mikulicic 0:c0ecb8bf28eb 31407 val_t arg = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31408 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 31409 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31410 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31411 }
Marko Mikulicic 0:c0ecb8bf28eb 31412 d = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 31413 }
Marko Mikulicic 0:c0ecb8bf28eb 31414 if (isnan(d) || d < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31415 d = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 31416 } else if (isinf(d) || d > len1) {
Marko Mikulicic 0:c0ecb8bf28eb 31417 d = len1;
Marko Mikulicic 0:c0ecb8bf28eb 31418 }
Marko Mikulicic 0:c0ecb8bf28eb 31419 fromIndex = d;
Marko Mikulicic 0:c0ecb8bf28eb 31420
Marko Mikulicic 0:c0ecb8bf28eb 31421 /* adjust pointers accordingly to `fromIndex` */
Marko Mikulicic 0:c0ecb8bf28eb 31422 if (last) {
Marko Mikulicic 0:c0ecb8bf28eb 31423 const char *end_tmp = utfnshift(p1, fromIndex + len2);
Marko Mikulicic 0:c0ecb8bf28eb 31424 end = (end_tmp < end) ? end_tmp : end;
Marko Mikulicic 0:c0ecb8bf28eb 31425 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31426 p1 = utfnshift(p1, fromIndex);
Marko Mikulicic 0:c0ecb8bf28eb 31427 }
Marko Mikulicic 0:c0ecb8bf28eb 31428 }
Marko Mikulicic 0:c0ecb8bf28eb 31429
Marko Mikulicic 0:c0ecb8bf28eb 31430 /*
Marko Mikulicic 0:c0ecb8bf28eb 31431 * TODO(dfrank): when `last` is set, start from the end and look
Marko Mikulicic 0:c0ecb8bf28eb 31432 * backward. We'll need to improve `utfnshift()` for that, so that it can
Marko Mikulicic 0:c0ecb8bf28eb 31433 * handle negative offsets.
Marko Mikulicic 0:c0ecb8bf28eb 31434 */
Marko Mikulicic 0:c0ecb8bf28eb 31435 for (i = 0; p1 <= (end - bytecnt2); i++, p1 = utfnshift(p1, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 31436 if (memcmp(p1, p2, bytecnt2) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31437 dres = i;
Marko Mikulicic 0:c0ecb8bf28eb 31438 if (!last) break;
Marko Mikulicic 0:c0ecb8bf28eb 31439 }
Marko Mikulicic 0:c0ecb8bf28eb 31440 }
Marko Mikulicic 0:c0ecb8bf28eb 31441 }
Marko Mikulicic 0:c0ecb8bf28eb 31442 }
Marko Mikulicic 0:c0ecb8bf28eb 31443 if (!last && dres >= 0) dres += fromIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31444 *res = v7_mk_number(v7, dres);
Marko Mikulicic 0:c0ecb8bf28eb 31445
Marko Mikulicic 0:c0ecb8bf28eb 31446 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31447 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31448 }
Marko Mikulicic 0:c0ecb8bf28eb 31449
Marko Mikulicic 0:c0ecb8bf28eb 31450 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31451 V7_PRIVATE enum v7_err Str_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31452 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31453 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31454
Marko Mikulicic 0:c0ecb8bf28eb 31455 if (!v7_is_string(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31456 (v7_is_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31457 v7_get_proto(v7, this_obj) != v7->vals.string_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 31458 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 31459 v7_throwf(v7, TYPE_ERROR, "String.valueOf called on non-string object");
Marko Mikulicic 0:c0ecb8bf28eb 31460 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31461 }
Marko Mikulicic 0:c0ecb8bf28eb 31462
Marko Mikulicic 0:c0ecb8bf28eb 31463 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 31464 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31465
Marko Mikulicic 0:c0ecb8bf28eb 31466 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31467 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31468 }
Marko Mikulicic 0:c0ecb8bf28eb 31469
Marko Mikulicic 0:c0ecb8bf28eb 31470 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31471 V7_PRIVATE enum v7_err Str_indexOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31472 return s_index_of(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 31473 }
Marko Mikulicic 0:c0ecb8bf28eb 31474
Marko Mikulicic 0:c0ecb8bf28eb 31475 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31476 V7_PRIVATE enum v7_err Str_lastIndexOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31477 return s_index_of(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 31478 }
Marko Mikulicic 0:c0ecb8bf28eb 31479
Marko Mikulicic 0:c0ecb8bf28eb 31480 #if V7_ENABLE__String__localeCompare
Marko Mikulicic 0:c0ecb8bf28eb 31481 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31482 V7_PRIVATE enum v7_err Str_localeCompare(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31483 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31484 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31485 val_t arg0 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31486 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31487
Marko Mikulicic 0:c0ecb8bf28eb 31488 rcode = to_string(v7, v7_arg(v7, 0), &arg0, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31489 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31490 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31491 }
Marko Mikulicic 0:c0ecb8bf28eb 31492
Marko Mikulicic 0:c0ecb8bf28eb 31493 rcode = to_string(v7, this_obj, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31494 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31495 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31496 }
Marko Mikulicic 0:c0ecb8bf28eb 31497
Marko Mikulicic 0:c0ecb8bf28eb 31498 *res = v7_mk_number(v7, s_cmp(v7, s, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 31499
Marko Mikulicic 0:c0ecb8bf28eb 31500 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31501 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31502 }
Marko Mikulicic 0:c0ecb8bf28eb 31503 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31504
Marko Mikulicic 0:c0ecb8bf28eb 31505 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31506 V7_PRIVATE enum v7_err Str_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31507 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31508 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31509
Marko Mikulicic 0:c0ecb8bf28eb 31510 if (this_obj == v7->vals.string_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 31511 *res = v7_mk_string(v7, "false", 5, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31512 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31513 }
Marko Mikulicic 0:c0ecb8bf28eb 31514
Marko Mikulicic 0:c0ecb8bf28eb 31515 if (!v7_is_string(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31516 !(v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31517 is_prototype_of(v7, this_obj, v7->vals.string_prototype))) {
Marko Mikulicic 0:c0ecb8bf28eb 31518 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 31519 "String.toString called on non-string object");
Marko Mikulicic 0:c0ecb8bf28eb 31520 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31521 }
Marko Mikulicic 0:c0ecb8bf28eb 31522
Marko Mikulicic 0:c0ecb8bf28eb 31523 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 31524 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31525 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31526 }
Marko Mikulicic 0:c0ecb8bf28eb 31527
Marko Mikulicic 0:c0ecb8bf28eb 31528 rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31529 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31530 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31531 }
Marko Mikulicic 0:c0ecb8bf28eb 31532
Marko Mikulicic 0:c0ecb8bf28eb 31533 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31534 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31535 }
Marko Mikulicic 0:c0ecb8bf28eb 31536
Marko Mikulicic 0:c0ecb8bf28eb 31537 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31538 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31539 enum v7_err call_regex_ctor(struct v7 *v7, val_t arg, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31540 /* TODO(mkm): make general helper out of this */
Marko Mikulicic 0:c0ecb8bf28eb 31541 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31542 val_t saved_args = v7->vals.arguments, args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31543 v7_array_push(v7, args, arg);
Marko Mikulicic 0:c0ecb8bf28eb 31544 v7->vals.arguments = args;
Marko Mikulicic 0:c0ecb8bf28eb 31545
Marko Mikulicic 0:c0ecb8bf28eb 31546 rcode = Regex_ctor(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 31547 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31548 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31549 }
Marko Mikulicic 0:c0ecb8bf28eb 31550 v7->vals.arguments = saved_args;
Marko Mikulicic 0:c0ecb8bf28eb 31551
Marko Mikulicic 0:c0ecb8bf28eb 31552 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31553 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31554 }
Marko Mikulicic 0:c0ecb8bf28eb 31555
Marko Mikulicic 0:c0ecb8bf28eb 31556 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31557 V7_PRIVATE enum v7_err Str_match(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31558 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31559 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31560 val_t so = V7_UNDEFINED, ro = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31561 long previousLastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31562 int lastMatch = 1, n = 0, flag_g;
Marko Mikulicic 0:c0ecb8bf28eb 31563 struct v7_regexp *rxp;
Marko Mikulicic 0:c0ecb8bf28eb 31564
Marko Mikulicic 0:c0ecb8bf28eb 31565 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31566
Marko Mikulicic 0:c0ecb8bf28eb 31567 rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31568 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31569 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31570 }
Marko Mikulicic 0:c0ecb8bf28eb 31571
Marko Mikulicic 0:c0ecb8bf28eb 31572 if (v7_argc(v7) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31573 rcode = v7_mk_regexp(v7, "", 0, "", 0, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31574 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31575 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31576 }
Marko Mikulicic 0:c0ecb8bf28eb 31577 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31578 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31579 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31580 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31581 }
Marko Mikulicic 0:c0ecb8bf28eb 31582 }
Marko Mikulicic 0:c0ecb8bf28eb 31583
Marko Mikulicic 0:c0ecb8bf28eb 31584 if (!v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 31585 rcode = call_regex_ctor(v7, ro, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31586 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31587 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31588 }
Marko Mikulicic 0:c0ecb8bf28eb 31589 }
Marko Mikulicic 0:c0ecb8bf28eb 31590
Marko Mikulicic 0:c0ecb8bf28eb 31591 rxp = v7_get_regexp_struct(v7, ro);
Marko Mikulicic 0:c0ecb8bf28eb 31592 flag_g = slre_get_flags(rxp->compiled_regexp) & SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 31593 if (!flag_g) {
Marko Mikulicic 0:c0ecb8bf28eb 31594 rcode = rx_exec(v7, ro, so, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 31595 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31596 }
Marko Mikulicic 0:c0ecb8bf28eb 31597
Marko Mikulicic 0:c0ecb8bf28eb 31598 rxp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31599 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31600 while (lastMatch) {
Marko Mikulicic 0:c0ecb8bf28eb 31601 val_t result;
Marko Mikulicic 0:c0ecb8bf28eb 31602
Marko Mikulicic 0:c0ecb8bf28eb 31603 rcode = rx_exec(v7, ro, so, 1, &result);
Marko Mikulicic 0:c0ecb8bf28eb 31604 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31605 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31606 }
Marko Mikulicic 0:c0ecb8bf28eb 31607
Marko Mikulicic 0:c0ecb8bf28eb 31608 if (v7_is_null(result)) {
Marko Mikulicic 0:c0ecb8bf28eb 31609 lastMatch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31610 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31611 long thisIndex = rxp->lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31612 if (thisIndex == previousLastIndex) {
Marko Mikulicic 0:c0ecb8bf28eb 31613 previousLastIndex = thisIndex + 1;
Marko Mikulicic 0:c0ecb8bf28eb 31614 rxp->lastIndex = previousLastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31615 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31616 previousLastIndex = thisIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31617 }
Marko Mikulicic 0:c0ecb8bf28eb 31618 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 31619 v7_array_push_throwing(v7, *res, v7_array_get(v7, result, 0), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31620 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31621 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31622 }
Marko Mikulicic 0:c0ecb8bf28eb 31623 n++;
Marko Mikulicic 0:c0ecb8bf28eb 31624 }
Marko Mikulicic 0:c0ecb8bf28eb 31625 }
Marko Mikulicic 0:c0ecb8bf28eb 31626
Marko Mikulicic 0:c0ecb8bf28eb 31627 if (n == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31628 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31629 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31630 }
Marko Mikulicic 0:c0ecb8bf28eb 31631
Marko Mikulicic 0:c0ecb8bf28eb 31632 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31633 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31634 }
Marko Mikulicic 0:c0ecb8bf28eb 31635
Marko Mikulicic 0:c0ecb8bf28eb 31636 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31637 V7_PRIVATE enum v7_err Str_replace(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31638 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31639 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31640 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 31641 size_t s_len;
Marko Mikulicic 0:c0ecb8bf28eb 31642 /*
Marko Mikulicic 0:c0ecb8bf28eb 31643 * Buffer of temporary strings returned by the replacement funciton. Will be
Marko Mikulicic 0:c0ecb8bf28eb 31644 * allocated below if only the replacement is a function. We need to store
Marko Mikulicic 0:c0ecb8bf28eb 31645 * each string in a separate `val_t`, because string data of length <= 5 is
Marko Mikulicic 0:c0ecb8bf28eb 31646 * stored right in `val_t`, so if there's more than one replacement,
Marko Mikulicic 0:c0ecb8bf28eb 31647 * each subsequent replacement will overwrite the previous one.
Marko Mikulicic 0:c0ecb8bf28eb 31648 */
Marko Mikulicic 0:c0ecb8bf28eb 31649 val_t *tmp_str_buf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31650 val_t out_str_o;
Marko Mikulicic 0:c0ecb8bf28eb 31651 char *old_owned_mbuf_base = v7->owned_strings.buf;
Marko Mikulicic 0:c0ecb8bf28eb 31652 char *old_owned_mbuf_end = v7->owned_strings.buf + v7->owned_strings.len;
Marko Mikulicic 0:c0ecb8bf28eb 31653
Marko Mikulicic 0:c0ecb8bf28eb 31654 rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31655 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31656 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31657 }
Marko Mikulicic 0:c0ecb8bf28eb 31658
Marko Mikulicic 0:c0ecb8bf28eb 31659 s = v7_get_string(v7, &this_obj, &s_len);
Marko Mikulicic 0:c0ecb8bf28eb 31660
Marko Mikulicic 0:c0ecb8bf28eb 31661 if (s_len != 0 && v7_argc(v7) > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 31662 const char *const str_end = s + s_len;
Marko Mikulicic 0:c0ecb8bf28eb 31663 char *p = (char *) s;
Marko Mikulicic 0:c0ecb8bf28eb 31664 uint32_t out_sub_num = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31665 val_t ro = V7_UNDEFINED, str_func = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31666 struct slre_prog *prog;
Marko Mikulicic 0:c0ecb8bf28eb 31667 struct slre_cap out_sub[V7_RE_MAX_REPL_SUB], *ptok = out_sub;
Marko Mikulicic 0:c0ecb8bf28eb 31668 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 31669 int flag_g;
Marko Mikulicic 0:c0ecb8bf28eb 31670
Marko Mikulicic 0:c0ecb8bf28eb 31671 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31672 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31673 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31674 }
Marko Mikulicic 0:c0ecb8bf28eb 31675 rcode = obj_value_of(v7, v7_arg(v7, 1), &str_func);
Marko Mikulicic 0:c0ecb8bf28eb 31676 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31677 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31678 }
Marko Mikulicic 0:c0ecb8bf28eb 31679
Marko Mikulicic 0:c0ecb8bf28eb 31680 if (!v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 31681 rcode = call_regex_ctor(v7, ro, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31682 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31683 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31684 }
Marko Mikulicic 0:c0ecb8bf28eb 31685 }
Marko Mikulicic 0:c0ecb8bf28eb 31686 prog = v7_get_regexp_struct(v7, ro)->compiled_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 31687 flag_g = slre_get_flags(prog) & SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 31688
Marko Mikulicic 0:c0ecb8bf28eb 31689 if (!v7_is_callable(v7, str_func)) {
Marko Mikulicic 0:c0ecb8bf28eb 31690 rcode = to_string(v7, str_func, &str_func, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31691 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31692 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31693 }
Marko Mikulicic 0:c0ecb8bf28eb 31694 }
Marko Mikulicic 0:c0ecb8bf28eb 31695
Marko Mikulicic 0:c0ecb8bf28eb 31696 do {
Marko Mikulicic 0:c0ecb8bf28eb 31697 int i;
Marko Mikulicic 0:c0ecb8bf28eb 31698 if (slre_exec(prog, 0, p, str_end, &loot)) break;
Marko Mikulicic 0:c0ecb8bf28eb 31699 if (p != loot.caps->start) {
Marko Mikulicic 0:c0ecb8bf28eb 31700 ptok->start = p;
Marko Mikulicic 0:c0ecb8bf28eb 31701 ptok->end = loot.caps->start;
Marko Mikulicic 0:c0ecb8bf28eb 31702 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31703 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31704 }
Marko Mikulicic 0:c0ecb8bf28eb 31705
Marko Mikulicic 0:c0ecb8bf28eb 31706 if (v7_is_callable(v7, str_func)) { /* replace function */
Marko Mikulicic 0:c0ecb8bf28eb 31707 const char *rez_str;
Marko Mikulicic 0:c0ecb8bf28eb 31708 size_t rez_len;
Marko Mikulicic 0:c0ecb8bf28eb 31709 val_t arr = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31710
Marko Mikulicic 0:c0ecb8bf28eb 31711 for (i = 0; i < loot.num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31712 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 31713 v7, arr, v7_mk_string(v7, loot.caps[i].start,
Marko Mikulicic 0:c0ecb8bf28eb 31714 loot.caps[i].end - loot.caps[i].start, 1),
Marko Mikulicic 0:c0ecb8bf28eb 31715 NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31716 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31717 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31718 }
Marko Mikulicic 0:c0ecb8bf28eb 31719 }
Marko Mikulicic 0:c0ecb8bf28eb 31720 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 31721 v7, arr, v7_mk_number(v7, utfnlen(s, loot.caps[0].start - s)),
Marko Mikulicic 0:c0ecb8bf28eb 31722 NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31723 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31724 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31725 }
Marko Mikulicic 0:c0ecb8bf28eb 31726
Marko Mikulicic 0:c0ecb8bf28eb 31727 rcode = v7_array_push_throwing(v7, arr, this_obj, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31728 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31729 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31730 }
Marko Mikulicic 0:c0ecb8bf28eb 31731
Marko Mikulicic 0:c0ecb8bf28eb 31732 {
Marko Mikulicic 0:c0ecb8bf28eb 31733 val_t val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31734
Marko Mikulicic 0:c0ecb8bf28eb 31735 rcode = b_apply(v7, str_func, this_obj, arr, 0, &val);
Marko Mikulicic 0:c0ecb8bf28eb 31736 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31737 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31738 }
Marko Mikulicic 0:c0ecb8bf28eb 31739
Marko Mikulicic 0:c0ecb8bf28eb 31740 if (tmp_str_buf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 31741 tmp_str_buf = (val_t *) calloc(sizeof(val_t), V7_RE_MAX_REPL_SUB);
Marko Mikulicic 0:c0ecb8bf28eb 31742 }
Marko Mikulicic 0:c0ecb8bf28eb 31743
Marko Mikulicic 0:c0ecb8bf28eb 31744 rcode = to_string(v7, val, &tmp_str_buf[out_sub_num], NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31745 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31746 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31747 }
Marko Mikulicic 0:c0ecb8bf28eb 31748 }
Marko Mikulicic 0:c0ecb8bf28eb 31749 rez_str = v7_get_string(v7, &tmp_str_buf[out_sub_num], &rez_len);
Marko Mikulicic 0:c0ecb8bf28eb 31750 if (rez_len) {
Marko Mikulicic 0:c0ecb8bf28eb 31751 ptok->start = rez_str;
Marko Mikulicic 0:c0ecb8bf28eb 31752 ptok->end = rez_str + rez_len;
Marko Mikulicic 0:c0ecb8bf28eb 31753 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31754 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31755 }
Marko Mikulicic 0:c0ecb8bf28eb 31756 } else { /* replace string */
Marko Mikulicic 0:c0ecb8bf28eb 31757 struct slre_loot newsub;
Marko Mikulicic 0:c0ecb8bf28eb 31758 size_t f_len;
Marko Mikulicic 0:c0ecb8bf28eb 31759 const char *f_str = v7_get_string(v7, &str_func, &f_len);
Marko Mikulicic 0:c0ecb8bf28eb 31760 slre_replace(&loot, s, s_len, f_str, f_len, &newsub);
Marko Mikulicic 0:c0ecb8bf28eb 31761 for (i = 0; i < newsub.num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31762 ptok->start = newsub.caps[i].start;
Marko Mikulicic 0:c0ecb8bf28eb 31763 ptok->end = newsub.caps[i].end;
Marko Mikulicic 0:c0ecb8bf28eb 31764 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31765 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31766 }
Marko Mikulicic 0:c0ecb8bf28eb 31767 }
Marko Mikulicic 0:c0ecb8bf28eb 31768 p = (char *) loot.caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 31769 } while (flag_g && p < str_end);
Marko Mikulicic 0:c0ecb8bf28eb 31770 if (p <= str_end) {
Marko Mikulicic 0:c0ecb8bf28eb 31771 ptok->start = p;
Marko Mikulicic 0:c0ecb8bf28eb 31772 ptok->end = str_end;
Marko Mikulicic 0:c0ecb8bf28eb 31773 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31774 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31775 }
Marko Mikulicic 0:c0ecb8bf28eb 31776 out_str_o = v7_mk_string(v7, NULL, 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31777 ptok = out_sub;
Marko Mikulicic 0:c0ecb8bf28eb 31778 do {
Marko Mikulicic 0:c0ecb8bf28eb 31779 size_t ln = ptok->end - ptok->start;
Marko Mikulicic 0:c0ecb8bf28eb 31780 const char *ps = ptok->start;
Marko Mikulicic 0:c0ecb8bf28eb 31781 if (ptok->start >= old_owned_mbuf_base &&
Marko Mikulicic 0:c0ecb8bf28eb 31782 ptok->start < old_owned_mbuf_end) {
Marko Mikulicic 0:c0ecb8bf28eb 31783 ps += v7->owned_strings.buf - old_owned_mbuf_base;
Marko Mikulicic 0:c0ecb8bf28eb 31784 }
Marko Mikulicic 0:c0ecb8bf28eb 31785 out_str_o = s_concat(v7, out_str_o, v7_mk_string(v7, ps, ln, 1));
Marko Mikulicic 0:c0ecb8bf28eb 31786 p += ln;
Marko Mikulicic 0:c0ecb8bf28eb 31787 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31788 } while (--out_sub_num);
Marko Mikulicic 0:c0ecb8bf28eb 31789
Marko Mikulicic 0:c0ecb8bf28eb 31790 *res = out_str_o;
Marko Mikulicic 0:c0ecb8bf28eb 31791 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31792 }
Marko Mikulicic 0:c0ecb8bf28eb 31793
Marko Mikulicic 0:c0ecb8bf28eb 31794 *res = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 31795
Marko Mikulicic 0:c0ecb8bf28eb 31796 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31797 if (tmp_str_buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 31798 free(tmp_str_buf);
Marko Mikulicic 0:c0ecb8bf28eb 31799 tmp_str_buf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31800 }
Marko Mikulicic 0:c0ecb8bf28eb 31801 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31802 }
Marko Mikulicic 0:c0ecb8bf28eb 31803
Marko Mikulicic 0:c0ecb8bf28eb 31804 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31805 V7_PRIVATE enum v7_err Str_search(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31806 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31807 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31808 long utf_shift = -1;
Marko Mikulicic 0:c0ecb8bf28eb 31809
Marko Mikulicic 0:c0ecb8bf28eb 31810 if (v7_argc(v7) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31811 size_t s_len;
Marko Mikulicic 0:c0ecb8bf28eb 31812 struct slre_loot sub;
Marko Mikulicic 0:c0ecb8bf28eb 31813 val_t so = V7_UNDEFINED, ro = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31814 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 31815
Marko Mikulicic 0:c0ecb8bf28eb 31816 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31817 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31818 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31819 }
Marko Mikulicic 0:c0ecb8bf28eb 31820
Marko Mikulicic 0:c0ecb8bf28eb 31821 if (!v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 31822 rcode = call_regex_ctor(v7, ro, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31823 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31824 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31825 }
Marko Mikulicic 0:c0ecb8bf28eb 31826 }
Marko Mikulicic 0:c0ecb8bf28eb 31827
Marko Mikulicic 0:c0ecb8bf28eb 31828 rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31829 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31830 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31831 }
Marko Mikulicic 0:c0ecb8bf28eb 31832
Marko Mikulicic 0:c0ecb8bf28eb 31833 s = v7_get_string(v7, &so, &s_len);
Marko Mikulicic 0:c0ecb8bf28eb 31834
Marko Mikulicic 0:c0ecb8bf28eb 31835 if (!slre_exec(v7_get_regexp_struct(v7, ro)->compiled_regexp, 0, s,
Marko Mikulicic 0:c0ecb8bf28eb 31836 s + s_len, &sub))
Marko Mikulicic 0:c0ecb8bf28eb 31837 utf_shift = utfnlen(s, sub.caps[0].start - s); /* calc shift for UTF-8 */
Marko Mikulicic 0:c0ecb8bf28eb 31838 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31839 utf_shift = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31840 }
Marko Mikulicic 0:c0ecb8bf28eb 31841
Marko Mikulicic 0:c0ecb8bf28eb 31842 *res = v7_mk_number(v7, utf_shift);
Marko Mikulicic 0:c0ecb8bf28eb 31843
Marko Mikulicic 0:c0ecb8bf28eb 31844 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31845 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31846 }
Marko Mikulicic 0:c0ecb8bf28eb 31847
Marko Mikulicic 0:c0ecb8bf28eb 31848 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 31849
Marko Mikulicic 0:c0ecb8bf28eb 31850 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31851 V7_PRIVATE enum v7_err Str_slice(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31852 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31853 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31854 long from = 0, to = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31855 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 31856 val_t so = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31857 const char *begin, *end;
Marko Mikulicic 0:c0ecb8bf28eb 31858 int num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31859
Marko Mikulicic 0:c0ecb8bf28eb 31860 rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31861 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31862 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31863 }
Marko Mikulicic 0:c0ecb8bf28eb 31864
Marko Mikulicic 0:c0ecb8bf28eb 31865 begin = v7_get_string(v7, &so, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31866
Marko Mikulicic 0:c0ecb8bf28eb 31867 to = len = utfnlen(begin, len);
Marko Mikulicic 0:c0ecb8bf28eb 31868 if (num_args > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31869 rcode = to_long(v7, v7_arg(v7, 0), 0, &from);
Marko Mikulicic 0:c0ecb8bf28eb 31870 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31871 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31872 }
Marko Mikulicic 0:c0ecb8bf28eb 31873
Marko Mikulicic 0:c0ecb8bf28eb 31874 if (from < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31875 from += len;
Marko Mikulicic 0:c0ecb8bf28eb 31876 if (from < 0) from = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31877 } else if ((size_t) from > len)
Marko Mikulicic 0:c0ecb8bf28eb 31878 from = len;
Marko Mikulicic 0:c0ecb8bf28eb 31879 if (num_args > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 31880 rcode = to_long(v7, v7_arg(v7, 1), 0, &to);
Marko Mikulicic 0:c0ecb8bf28eb 31881 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31882 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31883 }
Marko Mikulicic 0:c0ecb8bf28eb 31884
Marko Mikulicic 0:c0ecb8bf28eb 31885 if (to < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31886 to += len;
Marko Mikulicic 0:c0ecb8bf28eb 31887 if (to < 0) to = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31888 } else if ((size_t) to > len)
Marko Mikulicic 0:c0ecb8bf28eb 31889 to = len;
Marko Mikulicic 0:c0ecb8bf28eb 31890 }
Marko Mikulicic 0:c0ecb8bf28eb 31891 }
Marko Mikulicic 0:c0ecb8bf28eb 31892
Marko Mikulicic 0:c0ecb8bf28eb 31893 if (from > to) to = from;
Marko Mikulicic 0:c0ecb8bf28eb 31894 end = utfnshift(begin, to);
Marko Mikulicic 0:c0ecb8bf28eb 31895 begin = utfnshift(begin, from);
Marko Mikulicic 0:c0ecb8bf28eb 31896
Marko Mikulicic 0:c0ecb8bf28eb 31897 *res = v7_mk_string(v7, begin, end - begin, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31898
Marko Mikulicic 0:c0ecb8bf28eb 31899 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31900 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31901 }
Marko Mikulicic 0:c0ecb8bf28eb 31902
Marko Mikulicic 0:c0ecb8bf28eb 31903 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31904 static enum v7_err s_transform(struct v7 *v7, val_t obj, Rune (*func)(Rune),
Marko Mikulicic 0:c0ecb8bf28eb 31905 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31906 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31907 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31908 size_t i, n, len;
Marko Mikulicic 0:c0ecb8bf28eb 31909 const char *p2, *p;
Marko Mikulicic 0:c0ecb8bf28eb 31910
Marko Mikulicic 0:c0ecb8bf28eb 31911 rcode = to_string(v7, obj, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31912 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31913 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31914 }
Marko Mikulicic 0:c0ecb8bf28eb 31915
Marko Mikulicic 0:c0ecb8bf28eb 31916 p = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31917
Marko Mikulicic 0:c0ecb8bf28eb 31918 /* Pass NULL to make sure we're not creating dictionary value */
Marko Mikulicic 0:c0ecb8bf28eb 31919 *res = v7_mk_string(v7, NULL, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31920
Marko Mikulicic 0:c0ecb8bf28eb 31921 {
Marko Mikulicic 0:c0ecb8bf28eb 31922 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 31923 p2 = v7_get_string(v7, res, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31924 for (i = 0; i < len; i += n) {
Marko Mikulicic 0:c0ecb8bf28eb 31925 n = chartorune(&r, p + i);
Marko Mikulicic 0:c0ecb8bf28eb 31926 r = func(r);
Marko Mikulicic 0:c0ecb8bf28eb 31927 runetochar((char *) p2 + i, &r);
Marko Mikulicic 0:c0ecb8bf28eb 31928 }
Marko Mikulicic 0:c0ecb8bf28eb 31929 }
Marko Mikulicic 0:c0ecb8bf28eb 31930
Marko Mikulicic 0:c0ecb8bf28eb 31931 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31932 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31933 }
Marko Mikulicic 0:c0ecb8bf28eb 31934
Marko Mikulicic 0:c0ecb8bf28eb 31935 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31936 V7_PRIVATE enum v7_err Str_toLowerCase(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31937 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31938 return s_transform(v7, this_obj, tolowerrune, res);
Marko Mikulicic 0:c0ecb8bf28eb 31939 }
Marko Mikulicic 0:c0ecb8bf28eb 31940
Marko Mikulicic 0:c0ecb8bf28eb 31941 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31942 V7_PRIVATE enum v7_err Str_toUpperCase(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31943 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31944 return s_transform(v7, this_obj, toupperrune, res);
Marko Mikulicic 0:c0ecb8bf28eb 31945 }
Marko Mikulicic 0:c0ecb8bf28eb 31946
Marko Mikulicic 0:c0ecb8bf28eb 31947 static int s_isspace(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 31948 return isspacerune(c) || isnewline(c);
Marko Mikulicic 0:c0ecb8bf28eb 31949 }
Marko Mikulicic 0:c0ecb8bf28eb 31950
Marko Mikulicic 0:c0ecb8bf28eb 31951 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31952 V7_PRIVATE enum v7_err Str_trim(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31953 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31954 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31955 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31956 size_t i, n, len, start = 0, end, state = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31957 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 31958 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 31959
Marko Mikulicic 0:c0ecb8bf28eb 31960 rcode = to_string(v7, this_obj, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31961 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31962 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31963 }
Marko Mikulicic 0:c0ecb8bf28eb 31964 p = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31965
Marko Mikulicic 0:c0ecb8bf28eb 31966 end = len;
Marko Mikulicic 0:c0ecb8bf28eb 31967 for (i = 0; i < len; i += n) {
Marko Mikulicic 0:c0ecb8bf28eb 31968 n = chartorune(&r, p + i);
Marko Mikulicic 0:c0ecb8bf28eb 31969 if (!s_isspace(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 31970 if (state++ == 0) start = i;
Marko Mikulicic 0:c0ecb8bf28eb 31971 end = i + n;
Marko Mikulicic 0:c0ecb8bf28eb 31972 }
Marko Mikulicic 0:c0ecb8bf28eb 31973 }
Marko Mikulicic 0:c0ecb8bf28eb 31974
Marko Mikulicic 0:c0ecb8bf28eb 31975 *res = v7_mk_string(v7, p + start, end - start, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31976
Marko Mikulicic 0:c0ecb8bf28eb 31977 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31978 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31979 }
Marko Mikulicic 0:c0ecb8bf28eb 31980
Marko Mikulicic 0:c0ecb8bf28eb 31981 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31982 V7_PRIVATE enum v7_err Str_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31983 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31984 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31985 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31986 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31987
Marko Mikulicic 0:c0ecb8bf28eb 31988 rcode = obj_value_of(v7, this_obj, &s);
Marko Mikulicic 0:c0ecb8bf28eb 31989 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31990 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31991 }
Marko Mikulicic 0:c0ecb8bf28eb 31992
Marko Mikulicic 0:c0ecb8bf28eb 31993 if (v7_is_string(s)) {
Marko Mikulicic 0:c0ecb8bf28eb 31994 const char *p = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31995 len = utfnlen(p, len);
Marko Mikulicic 0:c0ecb8bf28eb 31996 }
Marko Mikulicic 0:c0ecb8bf28eb 31997
Marko Mikulicic 0:c0ecb8bf28eb 31998 *res = v7_mk_number(v7, len);
Marko Mikulicic 0:c0ecb8bf28eb 31999 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32000 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32001 }
Marko Mikulicic 0:c0ecb8bf28eb 32002
Marko Mikulicic 0:c0ecb8bf28eb 32003 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32004 V7_PRIVATE enum v7_err Str_at(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32005 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32006 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32007 long arg0;
Marko Mikulicic 0:c0ecb8bf28eb 32008 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32009
Marko Mikulicic 0:c0ecb8bf28eb 32010 rcode = to_long(v7, v7_arg(v7, 0), -1, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 32011 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32012 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32013 }
Marko Mikulicic 0:c0ecb8bf28eb 32014
Marko Mikulicic 0:c0ecb8bf28eb 32015 rcode = obj_value_of(v7, this_obj, &s);
Marko Mikulicic 0:c0ecb8bf28eb 32016 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32017 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32018 }
Marko Mikulicic 0:c0ecb8bf28eb 32019
Marko Mikulicic 0:c0ecb8bf28eb 32020 if (v7_is_string(s)) {
Marko Mikulicic 0:c0ecb8bf28eb 32021 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 32022 const unsigned char *p = (unsigned char *) v7_get_string(v7, &s, &n);
Marko Mikulicic 0:c0ecb8bf28eb 32023 if (arg0 >= 0 && (size_t) arg0 < n) {
Marko Mikulicic 0:c0ecb8bf28eb 32024 *res = v7_mk_number(v7, p[arg0]);
Marko Mikulicic 0:c0ecb8bf28eb 32025 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32026 }
Marko Mikulicic 0:c0ecb8bf28eb 32027 }
Marko Mikulicic 0:c0ecb8bf28eb 32028
Marko Mikulicic 0:c0ecb8bf28eb 32029 *res = v7_mk_number(v7, NAN);
Marko Mikulicic 0:c0ecb8bf28eb 32030
Marko Mikulicic 0:c0ecb8bf28eb 32031 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32032 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32033 }
Marko Mikulicic 0:c0ecb8bf28eb 32034
Marko Mikulicic 0:c0ecb8bf28eb 32035 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32036 V7_PRIVATE enum v7_err Str_blen(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32037 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32038 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32039 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32040 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32041
Marko Mikulicic 0:c0ecb8bf28eb 32042 rcode = obj_value_of(v7, this_obj, &s);
Marko Mikulicic 0:c0ecb8bf28eb 32043 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32044 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32045 }
Marko Mikulicic 0:c0ecb8bf28eb 32046
Marko Mikulicic 0:c0ecb8bf28eb 32047 if (v7_is_string(s)) {
Marko Mikulicic 0:c0ecb8bf28eb 32048 v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 32049 }
Marko Mikulicic 0:c0ecb8bf28eb 32050
Marko Mikulicic 0:c0ecb8bf28eb 32051 *res = v7_mk_number(v7, len);
Marko Mikulicic 0:c0ecb8bf28eb 32052
Marko Mikulicic 0:c0ecb8bf28eb 32053 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32054 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32055 }
Marko Mikulicic 0:c0ecb8bf28eb 32056
Marko Mikulicic 0:c0ecb8bf28eb 32057 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32058 static enum v7_err s_substr(struct v7 *v7, val_t s, long start, long len,
Marko Mikulicic 0:c0ecb8bf28eb 32059 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32060 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32061 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 32062 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 32063
Marko Mikulicic 0:c0ecb8bf28eb 32064 rcode = to_string(v7, s, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32065 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32066 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32067 }
Marko Mikulicic 0:c0ecb8bf28eb 32068
Marko Mikulicic 0:c0ecb8bf28eb 32069 p = v7_get_string(v7, &s, &n);
Marko Mikulicic 0:c0ecb8bf28eb 32070 n = utfnlen(p, n);
Marko Mikulicic 0:c0ecb8bf28eb 32071
Marko Mikulicic 0:c0ecb8bf28eb 32072 if (start < (long) n && len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32073 if (start < 0) start = (long) n + start;
Marko Mikulicic 0:c0ecb8bf28eb 32074 if (start < 0) start = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32075
Marko Mikulicic 0:c0ecb8bf28eb 32076 if (start > (long) n) start = n;
Marko Mikulicic 0:c0ecb8bf28eb 32077 if (len < 0) len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32078 if (len > (long) n - start) len = n - start;
Marko Mikulicic 0:c0ecb8bf28eb 32079 p = utfnshift(p, start);
Marko Mikulicic 0:c0ecb8bf28eb 32080 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32081 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32082 }
Marko Mikulicic 0:c0ecb8bf28eb 32083
Marko Mikulicic 0:c0ecb8bf28eb 32084 *res = v7_mk_string(v7, p, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 32085
Marko Mikulicic 0:c0ecb8bf28eb 32086 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32087 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32088 }
Marko Mikulicic 0:c0ecb8bf28eb 32089
Marko Mikulicic 0:c0ecb8bf28eb 32090 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32091 V7_PRIVATE enum v7_err Str_substr(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32092 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32093 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32094 long start, len;
Marko Mikulicic 0:c0ecb8bf28eb 32095
Marko Mikulicic 0:c0ecb8bf28eb 32096 rcode = to_long(v7, v7_arg(v7, 0), 0, &start);
Marko Mikulicic 0:c0ecb8bf28eb 32097 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32098 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32099 }
Marko Mikulicic 0:c0ecb8bf28eb 32100
Marko Mikulicic 0:c0ecb8bf28eb 32101 rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &len);
Marko Mikulicic 0:c0ecb8bf28eb 32102 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32103 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32104 }
Marko Mikulicic 0:c0ecb8bf28eb 32105
Marko Mikulicic 0:c0ecb8bf28eb 32106 rcode = s_substr(v7, this_obj, start, len, res);
Marko Mikulicic 0:c0ecb8bf28eb 32107 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32108 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32109 }
Marko Mikulicic 0:c0ecb8bf28eb 32110
Marko Mikulicic 0:c0ecb8bf28eb 32111 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32112 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32113 }
Marko Mikulicic 0:c0ecb8bf28eb 32114
Marko Mikulicic 0:c0ecb8bf28eb 32115 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32116 V7_PRIVATE enum v7_err Str_substring(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32117 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32118 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32119 long start, end;
Marko Mikulicic 0:c0ecb8bf28eb 32120
Marko Mikulicic 0:c0ecb8bf28eb 32121 rcode = to_long(v7, v7_arg(v7, 0), 0, &start);
Marko Mikulicic 0:c0ecb8bf28eb 32122 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32123 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32124 }
Marko Mikulicic 0:c0ecb8bf28eb 32125
Marko Mikulicic 0:c0ecb8bf28eb 32126 rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &end);
Marko Mikulicic 0:c0ecb8bf28eb 32127 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32128 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32129 }
Marko Mikulicic 0:c0ecb8bf28eb 32130
Marko Mikulicic 0:c0ecb8bf28eb 32131 if (start < 0) start = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32132 if (end < 0) end = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32133 if (start > end) {
Marko Mikulicic 0:c0ecb8bf28eb 32134 long tmp = start;
Marko Mikulicic 0:c0ecb8bf28eb 32135 start = end;
Marko Mikulicic 0:c0ecb8bf28eb 32136 end = tmp;
Marko Mikulicic 0:c0ecb8bf28eb 32137 }
Marko Mikulicic 0:c0ecb8bf28eb 32138
Marko Mikulicic 0:c0ecb8bf28eb 32139 rcode = s_substr(v7, this_obj, start, end - start, res);
Marko Mikulicic 0:c0ecb8bf28eb 32140 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32141
Marko Mikulicic 0:c0ecb8bf28eb 32142 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32143 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32144 }
Marko Mikulicic 0:c0ecb8bf28eb 32145
Marko Mikulicic 0:c0ecb8bf28eb 32146 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32147 V7_PRIVATE enum v7_err Str_split(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32148 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32149 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32150 const char *s, *s_end;
Marko Mikulicic 0:c0ecb8bf28eb 32151 size_t s_len;
Marko Mikulicic 0:c0ecb8bf28eb 32152 long num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32153 rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32154 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32155 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32156 }
Marko Mikulicic 0:c0ecb8bf28eb 32157 s = v7_get_string(v7, &this_obj, &s_len);
Marko Mikulicic 0:c0ecb8bf28eb 32158 s_end = s + s_len;
Marko Mikulicic 0:c0ecb8bf28eb 32159
Marko Mikulicic 0:c0ecb8bf28eb 32160 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32161
Marko Mikulicic 0:c0ecb8bf28eb 32162 if (num_args == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32163 /*
Marko Mikulicic 0:c0ecb8bf28eb 32164 * No arguments were given: resulting array will contain just a single
Marko Mikulicic 0:c0ecb8bf28eb 32165 * element: the source string
Marko Mikulicic 0:c0ecb8bf28eb 32166 */
Marko Mikulicic 0:c0ecb8bf28eb 32167 rcode = v7_array_push_throwing(v7, *res, this_obj, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32168 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32169 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32170 }
Marko Mikulicic 0:c0ecb8bf28eb 32171 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32172 val_t ro = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32173 long elem, limit;
Marko Mikulicic 0:c0ecb8bf28eb 32174 size_t lookup_idx = 0, substr_idx = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32175 struct _str_split_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 32176
Marko Mikulicic 0:c0ecb8bf28eb 32177 rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &limit);
Marko Mikulicic 0:c0ecb8bf28eb 32178 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32179 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32180 }
Marko Mikulicic 0:c0ecb8bf28eb 32181
Marko Mikulicic 0:c0ecb8bf28eb 32182 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 32183 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32184 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32185 }
Marko Mikulicic 0:c0ecb8bf28eb 32186
Marko Mikulicic 0:c0ecb8bf28eb 32187 /* Initialize substring context depending on the argument type */
Marko Mikulicic 0:c0ecb8bf28eb 32188 if (v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 32189 /* use RegExp implementation */
Marko Mikulicic 0:c0ecb8bf28eb 32190 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32191 ctx.p_init = subs_regexp_init;
Marko Mikulicic 0:c0ecb8bf28eb 32192 ctx.p_exec = subs_regexp_exec;
Marko Mikulicic 0:c0ecb8bf28eb 32193 ctx.p_add_caps = subs_regexp_split_add_caps;
Marko Mikulicic 0:c0ecb8bf28eb 32194 #else
Marko Mikulicic 0:c0ecb8bf28eb 32195 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 32196 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32197 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32198 /*
Marko Mikulicic 0:c0ecb8bf28eb 32199 * use String implementation: first of all, convert to String (if it's
Marko Mikulicic 0:c0ecb8bf28eb 32200 * not already a String)
Marko Mikulicic 0:c0ecb8bf28eb 32201 */
Marko Mikulicic 0:c0ecb8bf28eb 32202 rcode = to_string(v7, ro, &ro, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32203 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32204 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32205 }
Marko Mikulicic 0:c0ecb8bf28eb 32206
Marko Mikulicic 0:c0ecb8bf28eb 32207 ctx.p_init = subs_string_init;
Marko Mikulicic 0:c0ecb8bf28eb 32208 ctx.p_exec = subs_string_exec;
Marko Mikulicic 0:c0ecb8bf28eb 32209 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32210 ctx.p_add_caps = subs_string_split_add_caps;
Marko Mikulicic 0:c0ecb8bf28eb 32211 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32212 }
Marko Mikulicic 0:c0ecb8bf28eb 32213 /* initialize context */
Marko Mikulicic 0:c0ecb8bf28eb 32214 ctx.p_init(&ctx, v7, ro);
Marko Mikulicic 0:c0ecb8bf28eb 32215
Marko Mikulicic 0:c0ecb8bf28eb 32216 if (s_len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32217 /*
Marko Mikulicic 0:c0ecb8bf28eb 32218 * if `this` is (or converts to) an empty string, resulting array should
Marko Mikulicic 0:c0ecb8bf28eb 32219 * contain empty string if only separator does not match an empty string.
Marko Mikulicic 0:c0ecb8bf28eb 32220 * Otherwise, the array is left empty
Marko Mikulicic 0:c0ecb8bf28eb 32221 */
Marko Mikulicic 0:c0ecb8bf28eb 32222 int matches_empty = !ctx.p_exec(&ctx, s, s);
Marko Mikulicic 0:c0ecb8bf28eb 32223 if (!matches_empty) {
Marko Mikulicic 0:c0ecb8bf28eb 32224 rcode = v7_array_push_throwing(v7, *res, this_obj, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32225 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32226 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32227 }
Marko Mikulicic 0:c0ecb8bf28eb 32228 }
Marko Mikulicic 0:c0ecb8bf28eb 32229 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32230 size_t last_match_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32231
Marko Mikulicic 0:c0ecb8bf28eb 32232 for (elem = 0; elem < limit && lookup_idx < s_len;) {
Marko Mikulicic 0:c0ecb8bf28eb 32233 size_t substr_len;
Marko Mikulicic 0:c0ecb8bf28eb 32234 /* find next match, and break if there's no match */
Marko Mikulicic 0:c0ecb8bf28eb 32235 if (ctx.p_exec(&ctx, s + lookup_idx, s_end)) break;
Marko Mikulicic 0:c0ecb8bf28eb 32236
Marko Mikulicic 0:c0ecb8bf28eb 32237 last_match_len = ctx.match_end - ctx.match_start;
Marko Mikulicic 0:c0ecb8bf28eb 32238 substr_len = ctx.match_start - s - substr_idx;
Marko Mikulicic 0:c0ecb8bf28eb 32239
Marko Mikulicic 0:c0ecb8bf28eb 32240 /* add next substring to the resulting array, if needed */
Marko Mikulicic 0:c0ecb8bf28eb 32241 if (substr_len > 0 || last_match_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32242 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 32243 v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32244 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32245 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32246 }
Marko Mikulicic 0:c0ecb8bf28eb 32247 elem++;
Marko Mikulicic 0:c0ecb8bf28eb 32248
Marko Mikulicic 0:c0ecb8bf28eb 32249 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32250 /* Add captures (for RegExp only) */
Marko Mikulicic 0:c0ecb8bf28eb 32251 elem = ctx.p_add_caps(&ctx, *res, elem, limit);
Marko Mikulicic 0:c0ecb8bf28eb 32252 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32253 }
Marko Mikulicic 0:c0ecb8bf28eb 32254
Marko Mikulicic 0:c0ecb8bf28eb 32255 /* advance lookup_idx appropriately */
Marko Mikulicic 0:c0ecb8bf28eb 32256 if (last_match_len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32257 /* empty match: advance to the next char */
Marko Mikulicic 0:c0ecb8bf28eb 32258 const char *next = utfnshift((s + lookup_idx), 1);
Marko Mikulicic 0:c0ecb8bf28eb 32259 lookup_idx += (next - (s + lookup_idx));
Marko Mikulicic 0:c0ecb8bf28eb 32260 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32261 /* non-empty match: advance to the end of match */
Marko Mikulicic 0:c0ecb8bf28eb 32262 lookup_idx = ctx.match_end - s;
Marko Mikulicic 0:c0ecb8bf28eb 32263 }
Marko Mikulicic 0:c0ecb8bf28eb 32264
Marko Mikulicic 0:c0ecb8bf28eb 32265 /*
Marko Mikulicic 0:c0ecb8bf28eb 32266 * always remember the end of the match, so that next time we will take
Marko Mikulicic 0:c0ecb8bf28eb 32267 * substring from that position
Marko Mikulicic 0:c0ecb8bf28eb 32268 */
Marko Mikulicic 0:c0ecb8bf28eb 32269 substr_idx = ctx.match_end - s;
Marko Mikulicic 0:c0ecb8bf28eb 32270 }
Marko Mikulicic 0:c0ecb8bf28eb 32271
Marko Mikulicic 0:c0ecb8bf28eb 32272 /* add the last substring to the resulting array, if needed */
Marko Mikulicic 0:c0ecb8bf28eb 32273 if (elem < limit) {
Marko Mikulicic 0:c0ecb8bf28eb 32274 size_t substr_len = s_len - substr_idx;
Marko Mikulicic 0:c0ecb8bf28eb 32275 if (substr_len > 0 || last_match_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32276 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 32277 v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32278 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32279 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32280 }
Marko Mikulicic 0:c0ecb8bf28eb 32281 }
Marko Mikulicic 0:c0ecb8bf28eb 32282 }
Marko Mikulicic 0:c0ecb8bf28eb 32283 }
Marko Mikulicic 0:c0ecb8bf28eb 32284 }
Marko Mikulicic 0:c0ecb8bf28eb 32285
Marko Mikulicic 0:c0ecb8bf28eb 32286 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32287 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32288 }
Marko Mikulicic 0:c0ecb8bf28eb 32289
Marko Mikulicic 0:c0ecb8bf28eb 32290 V7_PRIVATE void init_string(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 32291 val_t str = mk_cfunction_obj_with_proto(v7, String_ctor, 1,
Marko Mikulicic 0:c0ecb8bf28eb 32292 v7->vals.string_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 32293 v7_def(v7, v7->vals.global_object, "String", 6, V7_DESC_ENUMERABLE(0), str);
Marko Mikulicic 0:c0ecb8bf28eb 32294
Marko Mikulicic 0:c0ecb8bf28eb 32295 set_cfunc_prop(v7, str, "fromCharCode", Str_fromCharCode);
Marko Mikulicic 0:c0ecb8bf28eb 32296 set_cfunc_prop(v7, v7->vals.string_prototype, "charCodeAt", Str_charCodeAt);
Marko Mikulicic 0:c0ecb8bf28eb 32297 set_cfunc_prop(v7, v7->vals.string_prototype, "charAt", Str_charAt);
Marko Mikulicic 0:c0ecb8bf28eb 32298 set_cfunc_prop(v7, v7->vals.string_prototype, "concat", Str_concat);
Marko Mikulicic 0:c0ecb8bf28eb 32299 set_cfunc_prop(v7, v7->vals.string_prototype, "indexOf", Str_indexOf);
Marko Mikulicic 0:c0ecb8bf28eb 32300 set_cfunc_prop(v7, v7->vals.string_prototype, "substr", Str_substr);
Marko Mikulicic 0:c0ecb8bf28eb 32301 set_cfunc_prop(v7, v7->vals.string_prototype, "substring", Str_substring);
Marko Mikulicic 0:c0ecb8bf28eb 32302 set_cfunc_prop(v7, v7->vals.string_prototype, "valueOf", Str_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 32303 set_cfunc_prop(v7, v7->vals.string_prototype, "lastIndexOf", Str_lastIndexOf);
Marko Mikulicic 0:c0ecb8bf28eb 32304 #if V7_ENABLE__String__localeCompare
Marko Mikulicic 0:c0ecb8bf28eb 32305 set_cfunc_prop(v7, v7->vals.string_prototype, "localeCompare",
Marko Mikulicic 0:c0ecb8bf28eb 32306 Str_localeCompare);
Marko Mikulicic 0:c0ecb8bf28eb 32307 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32308 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32309 set_cfunc_prop(v7, v7->vals.string_prototype, "match", Str_match);
Marko Mikulicic 0:c0ecb8bf28eb 32310 set_cfunc_prop(v7, v7->vals.string_prototype, "replace", Str_replace);
Marko Mikulicic 0:c0ecb8bf28eb 32311 set_cfunc_prop(v7, v7->vals.string_prototype, "search", Str_search);
Marko Mikulicic 0:c0ecb8bf28eb 32312 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32313 set_cfunc_prop(v7, v7->vals.string_prototype, "split", Str_split);
Marko Mikulicic 0:c0ecb8bf28eb 32314 set_cfunc_prop(v7, v7->vals.string_prototype, "slice", Str_slice);
Marko Mikulicic 0:c0ecb8bf28eb 32315 set_cfunc_prop(v7, v7->vals.string_prototype, "trim", Str_trim);
Marko Mikulicic 0:c0ecb8bf28eb 32316 set_cfunc_prop(v7, v7->vals.string_prototype, "toLowerCase", Str_toLowerCase);
Marko Mikulicic 0:c0ecb8bf28eb 32317 #if V7_ENABLE__String__localeLowerCase
Marko Mikulicic 0:c0ecb8bf28eb 32318 set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleLowerCase",
Marko Mikulicic 0:c0ecb8bf28eb 32319 Str_toLowerCase);
Marko Mikulicic 0:c0ecb8bf28eb 32320 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32321 set_cfunc_prop(v7, v7->vals.string_prototype, "toUpperCase", Str_toUpperCase);
Marko Mikulicic 0:c0ecb8bf28eb 32322 #if V7_ENABLE__String__localeUpperCase
Marko Mikulicic 0:c0ecb8bf28eb 32323 set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleUpperCase",
Marko Mikulicic 0:c0ecb8bf28eb 32324 Str_toUpperCase);
Marko Mikulicic 0:c0ecb8bf28eb 32325 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32326 set_cfunc_prop(v7, v7->vals.string_prototype, "toString", Str_toString);
Marko Mikulicic 0:c0ecb8bf28eb 32327
Marko Mikulicic 0:c0ecb8bf28eb 32328 v7_def(v7, v7->vals.string_prototype, "length", 6, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 32329 v7_mk_cfunction(Str_length));
Marko Mikulicic 0:c0ecb8bf28eb 32330
Marko Mikulicic 0:c0ecb8bf28eb 32331 /* Non-standard Cesanta extension */
Marko Mikulicic 0:c0ecb8bf28eb 32332 set_cfunc_prop(v7, v7->vals.string_prototype, "at", Str_at);
Marko Mikulicic 0:c0ecb8bf28eb 32333 v7_def(v7, v7->vals.string_prototype, "blen", 4, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 32334 v7_mk_cfunction(Str_blen));
Marko Mikulicic 0:c0ecb8bf28eb 32335 }
Marko Mikulicic 0:c0ecb8bf28eb 32336 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 32337 #line 1 "v7/src/std_date.c"
Marko Mikulicic 0:c0ecb8bf28eb 32338 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32339 /*
Marko Mikulicic 0:c0ecb8bf28eb 32340 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 32341 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 32342 */
Marko Mikulicic 0:c0ecb8bf28eb 32343
Marko Mikulicic 0:c0ecb8bf28eb 32344 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32345 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32346 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32347 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32348 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32349 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32350 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32351 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32352 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32353 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32354 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32355
Marko Mikulicic 0:c0ecb8bf28eb 32356 #if V7_ENABLE__Date
Marko Mikulicic 0:c0ecb8bf28eb 32357
Marko Mikulicic 0:c0ecb8bf28eb 32358 #include <locale.h>
Marko Mikulicic 0:c0ecb8bf28eb 32359 #include <time.h>
Marko Mikulicic 0:c0ecb8bf28eb 32360
Marko Mikulicic 0:c0ecb8bf28eb 32361 #ifndef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 32362 extern long timezone;
Marko Mikulicic 0:c0ecb8bf28eb 32363 #include <sys/time.h>
Marko Mikulicic 0:c0ecb8bf28eb 32364 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32365
Marko Mikulicic 0:c0ecb8bf28eb 32366 #if defined(_MSC_VER)
Marko Mikulicic 0:c0ecb8bf28eb 32367 #define timezone _timezone
Marko Mikulicic 0:c0ecb8bf28eb 32368 #define tzname _tzname
Marko Mikulicic 0:c0ecb8bf28eb 32369 #if _MSC_VER >= 1800
Marko Mikulicic 0:c0ecb8bf28eb 32370 #define tzset _tzset
Marko Mikulicic 0:c0ecb8bf28eb 32371 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32372 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32373
Marko Mikulicic 0:c0ecb8bf28eb 32374 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 32375 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 32376 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 32377
Marko Mikulicic 0:c0ecb8bf28eb 32378 typedef double etime_t; /* double is suitable type for ECMA time */
Marko Mikulicic 0:c0ecb8bf28eb 32379 /* inernally we have to use 64-bit integer for some operations */
Marko Mikulicic 0:c0ecb8bf28eb 32380 typedef int64_t etimeint_t;
Marko Mikulicic 0:c0ecb8bf28eb 32381 #define INVALID_TIME NAN
Marko Mikulicic 0:c0ecb8bf28eb 32382
Marko Mikulicic 0:c0ecb8bf28eb 32383 #define msPerDay 86400000
Marko Mikulicic 0:c0ecb8bf28eb 32384 #define HoursPerDay 24
Marko Mikulicic 0:c0ecb8bf28eb 32385 #define MinutesPerHour 60
Marko Mikulicic 0:c0ecb8bf28eb 32386 #define SecondsPerMinute 60
Marko Mikulicic 0:c0ecb8bf28eb 32387 #define SecondsPerHour 3600
Marko Mikulicic 0:c0ecb8bf28eb 32388 #define msPerSecond 1000
Marko Mikulicic 0:c0ecb8bf28eb 32389 #define msPerMinute 60000
Marko Mikulicic 0:c0ecb8bf28eb 32390 #define msPerHour 3600000
Marko Mikulicic 0:c0ecb8bf28eb 32391 #define MonthsInYear 12
Marko Mikulicic 0:c0ecb8bf28eb 32392
Marko Mikulicic 0:c0ecb8bf28eb 32393 /* ECMA alternative to struct tm */
Marko Mikulicic 0:c0ecb8bf28eb 32394 struct timeparts {
Marko Mikulicic 0:c0ecb8bf28eb 32395 int year; /* can be negative, up to +-282000 */
Marko Mikulicic 0:c0ecb8bf28eb 32396 int month; /* 0-11 */
Marko Mikulicic 0:c0ecb8bf28eb 32397 int day; /* 1-31 */
Marko Mikulicic 0:c0ecb8bf28eb 32398 int hour; /* 0-23 */
Marko Mikulicic 0:c0ecb8bf28eb 32399 int min; /* 0-59 */
Marko Mikulicic 0:c0ecb8bf28eb 32400 int sec; /* 0-59 */
Marko Mikulicic 0:c0ecb8bf28eb 32401 int msec;
Marko Mikulicic 0:c0ecb8bf28eb 32402 int dayofweek; /* 0-6 */
Marko Mikulicic 0:c0ecb8bf28eb 32403 };
Marko Mikulicic 0:c0ecb8bf28eb 32404
Marko Mikulicic 0:c0ecb8bf28eb 32405 static etimeint_t g_gmtoffms; /* timezone offset, ms, no DST */
Marko Mikulicic 0:c0ecb8bf28eb 32406 static const char *g_tzname; /* current timezone name */
Marko Mikulicic 0:c0ecb8bf28eb 32407
Marko Mikulicic 0:c0ecb8bf28eb 32408 /* Leap year formula copied from ECMA 5.1 standart as is */
Marko Mikulicic 0:c0ecb8bf28eb 32409 static int ecma_DaysInYear(int y) {
Marko Mikulicic 0:c0ecb8bf28eb 32410 if (y % 4 != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32411 return 365;
Marko Mikulicic 0:c0ecb8bf28eb 32412 } else if (y % 4 == 0 && y % 100 != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32413 return 366;
Marko Mikulicic 0:c0ecb8bf28eb 32414 } else if (y % 100 == 0 && y % 400 != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32415 return 365;
Marko Mikulicic 0:c0ecb8bf28eb 32416 } else if (y % 400 == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32417 return 366;
Marko Mikulicic 0:c0ecb8bf28eb 32418 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32419 return 365;
Marko Mikulicic 0:c0ecb8bf28eb 32420 }
Marko Mikulicic 0:c0ecb8bf28eb 32421 }
Marko Mikulicic 0:c0ecb8bf28eb 32422
Marko Mikulicic 0:c0ecb8bf28eb 32423 static etimeint_t ecma_DayFromYear(etimeint_t y) {
Marko Mikulicic 0:c0ecb8bf28eb 32424 return 365 * (y - 1970) + floor((y - 1969) / 4) - floor((y - 1901) / 100) +
Marko Mikulicic 0:c0ecb8bf28eb 32425 floor((y - 1601) / 400);
Marko Mikulicic 0:c0ecb8bf28eb 32426 }
Marko Mikulicic 0:c0ecb8bf28eb 32427
Marko Mikulicic 0:c0ecb8bf28eb 32428 static etimeint_t ecma_TimeFromYear(etimeint_t y) {
Marko Mikulicic 0:c0ecb8bf28eb 32429 return msPerDay * ecma_DayFromYear(y);
Marko Mikulicic 0:c0ecb8bf28eb 32430 }
Marko Mikulicic 0:c0ecb8bf28eb 32431
Marko Mikulicic 0:c0ecb8bf28eb 32432 static int ecma_IsLeapYear(int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32433 return ecma_DaysInYear(year) == 366;
Marko Mikulicic 0:c0ecb8bf28eb 32434 }
Marko Mikulicic 0:c0ecb8bf28eb 32435
Marko Mikulicic 0:c0ecb8bf28eb 32436 static int *ecma_getfirstdays(int isleap) {
Marko Mikulicic 0:c0ecb8bf28eb 32437 static int sdays[2][MonthsInYear + 1] = {
Marko Mikulicic 0:c0ecb8bf28eb 32438 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
Marko Mikulicic 0:c0ecb8bf28eb 32439 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
Marko Mikulicic 0:c0ecb8bf28eb 32440
Marko Mikulicic 0:c0ecb8bf28eb 32441 return sdays[isleap];
Marko Mikulicic 0:c0ecb8bf28eb 32442 }
Marko Mikulicic 0:c0ecb8bf28eb 32443
Marko Mikulicic 0:c0ecb8bf28eb 32444 static int ecma_DaylightSavingTA(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32445 time_t time = t / 1000;
Marko Mikulicic 0:c0ecb8bf28eb 32446 /*
Marko Mikulicic 0:c0ecb8bf28eb 32447 * Win32 doesn't have locatime_r
Marko Mikulicic 0:c0ecb8bf28eb 32448 * nixes don't have localtime_s
Marko Mikulicic 0:c0ecb8bf28eb 32449 * as result using localtime
Marko Mikulicic 0:c0ecb8bf28eb 32450 */
Marko Mikulicic 0:c0ecb8bf28eb 32451 struct tm *tm = localtime(&time);
Marko Mikulicic 0:c0ecb8bf28eb 32452 if (tm == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 32453 /* doesn't work on windows for times before epoch */
Marko Mikulicic 0:c0ecb8bf28eb 32454 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32455 }
Marko Mikulicic 0:c0ecb8bf28eb 32456 if (tm->tm_isdst > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32457 return msPerHour;
Marko Mikulicic 0:c0ecb8bf28eb 32458 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32459 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32460 }
Marko Mikulicic 0:c0ecb8bf28eb 32461 }
Marko Mikulicic 0:c0ecb8bf28eb 32462
Marko Mikulicic 0:c0ecb8bf28eb 32463 static int ecma_LocalTZA(void) {
Marko Mikulicic 0:c0ecb8bf28eb 32464 return (int) -g_gmtoffms;
Marko Mikulicic 0:c0ecb8bf28eb 32465 }
Marko Mikulicic 0:c0ecb8bf28eb 32466
Marko Mikulicic 0:c0ecb8bf28eb 32467 static etimeint_t ecma_UTC(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32468 return t - ecma_LocalTZA() - ecma_DaylightSavingTA(t - ecma_LocalTZA());
Marko Mikulicic 0:c0ecb8bf28eb 32469 }
Marko Mikulicic 0:c0ecb8bf28eb 32470
Marko Mikulicic 0:c0ecb8bf28eb 32471 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32472 V7_ENABLE__Date__toJSON || V7_ENABLE__Date__getters || \
Marko Mikulicic 0:c0ecb8bf28eb 32473 V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 32474 static int ecma_YearFromTime_s(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32475 int first = floor((t / msPerDay) / 366) + 1970,
Marko Mikulicic 0:c0ecb8bf28eb 32476 last = floor((t / msPerDay) / 365) + 1970, middle = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32477
Marko Mikulicic 0:c0ecb8bf28eb 32478 if (last < first) {
Marko Mikulicic 0:c0ecb8bf28eb 32479 int temp = first;
Marko Mikulicic 0:c0ecb8bf28eb 32480 first = last;
Marko Mikulicic 0:c0ecb8bf28eb 32481 last = temp;
Marko Mikulicic 0:c0ecb8bf28eb 32482 }
Marko Mikulicic 0:c0ecb8bf28eb 32483
Marko Mikulicic 0:c0ecb8bf28eb 32484 while (last > first) {
Marko Mikulicic 0:c0ecb8bf28eb 32485 middle = (last + first) / 2;
Marko Mikulicic 0:c0ecb8bf28eb 32486 if (ecma_TimeFromYear(middle) > t) {
Marko Mikulicic 0:c0ecb8bf28eb 32487 last = middle - 1;
Marko Mikulicic 0:c0ecb8bf28eb 32488 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32489 if (ecma_TimeFromYear(middle) <= t) {
Marko Mikulicic 0:c0ecb8bf28eb 32490 if (ecma_TimeFromYear(middle + 1) > t) {
Marko Mikulicic 0:c0ecb8bf28eb 32491 first = middle;
Marko Mikulicic 0:c0ecb8bf28eb 32492 break;
Marko Mikulicic 0:c0ecb8bf28eb 32493 }
Marko Mikulicic 0:c0ecb8bf28eb 32494 first = middle + 1;
Marko Mikulicic 0:c0ecb8bf28eb 32495 }
Marko Mikulicic 0:c0ecb8bf28eb 32496 }
Marko Mikulicic 0:c0ecb8bf28eb 32497 }
Marko Mikulicic 0:c0ecb8bf28eb 32498
Marko Mikulicic 0:c0ecb8bf28eb 32499 return first;
Marko Mikulicic 0:c0ecb8bf28eb 32500 }
Marko Mikulicic 0:c0ecb8bf28eb 32501
Marko Mikulicic 0:c0ecb8bf28eb 32502 static etimeint_t ecma_Day(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32503 return floor(t / msPerDay);
Marko Mikulicic 0:c0ecb8bf28eb 32504 }
Marko Mikulicic 0:c0ecb8bf28eb 32505
Marko Mikulicic 0:c0ecb8bf28eb 32506 static int ecma_DayWithinYear(etime_t t, int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32507 return (int) (ecma_Day(t) - ecma_DayFromYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32508 }
Marko Mikulicic 0:c0ecb8bf28eb 32509
Marko Mikulicic 0:c0ecb8bf28eb 32510 static int ecma_MonthFromTime(etime_t t, int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32511 int *days, i;
Marko Mikulicic 0:c0ecb8bf28eb 32512 etimeint_t dwy = ecma_DayWithinYear(t, year);
Marko Mikulicic 0:c0ecb8bf28eb 32513
Marko Mikulicic 0:c0ecb8bf28eb 32514 days = ecma_getfirstdays(ecma_IsLeapYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32515
Marko Mikulicic 0:c0ecb8bf28eb 32516 for (i = 0; i < MonthsInYear; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32517 if (dwy >= days[i] && dwy < days[i + 1]) {
Marko Mikulicic 0:c0ecb8bf28eb 32518 return i;
Marko Mikulicic 0:c0ecb8bf28eb 32519 }
Marko Mikulicic 0:c0ecb8bf28eb 32520 }
Marko Mikulicic 0:c0ecb8bf28eb 32521
Marko Mikulicic 0:c0ecb8bf28eb 32522 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 32523 }
Marko Mikulicic 0:c0ecb8bf28eb 32524
Marko Mikulicic 0:c0ecb8bf28eb 32525 static int ecma_DateFromTime(etime_t t, int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32526 int *days, mft = ecma_MonthFromTime(t, year),
Marko Mikulicic 0:c0ecb8bf28eb 32527 dwy = ecma_DayWithinYear(t, year);
Marko Mikulicic 0:c0ecb8bf28eb 32528
Marko Mikulicic 0:c0ecb8bf28eb 32529 if (mft > 11) {
Marko Mikulicic 0:c0ecb8bf28eb 32530 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 32531 }
Marko Mikulicic 0:c0ecb8bf28eb 32532
Marko Mikulicic 0:c0ecb8bf28eb 32533 days = ecma_getfirstdays(ecma_IsLeapYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32534
Marko Mikulicic 0:c0ecb8bf28eb 32535 return dwy - days[mft] + 1;
Marko Mikulicic 0:c0ecb8bf28eb 32536 }
Marko Mikulicic 0:c0ecb8bf28eb 32537
Marko Mikulicic 0:c0ecb8bf28eb 32538 #define DEF_EXTRACT_TIMEPART(funcname, c1, c2) \
Marko Mikulicic 0:c0ecb8bf28eb 32539 static int ecma_##funcname(etime_t t) { \
Marko Mikulicic 0:c0ecb8bf28eb 32540 int ret = (etimeint_t) floor(t / c1) % c2; \
Marko Mikulicic 0:c0ecb8bf28eb 32541 if (ret < 0) { \
Marko Mikulicic 0:c0ecb8bf28eb 32542 ret += c2; \
Marko Mikulicic 0:c0ecb8bf28eb 32543 } \
Marko Mikulicic 0:c0ecb8bf28eb 32544 return ret; \
Marko Mikulicic 0:c0ecb8bf28eb 32545 }
Marko Mikulicic 0:c0ecb8bf28eb 32546
Marko Mikulicic 0:c0ecb8bf28eb 32547 DEF_EXTRACT_TIMEPART(HourFromTime, msPerHour, HoursPerDay)
Marko Mikulicic 0:c0ecb8bf28eb 32548 DEF_EXTRACT_TIMEPART(MinFromTime, msPerMinute, MinutesPerHour)
Marko Mikulicic 0:c0ecb8bf28eb 32549 DEF_EXTRACT_TIMEPART(SecFromTime, msPerSecond, SecondsPerMinute)
Marko Mikulicic 0:c0ecb8bf28eb 32550 DEF_EXTRACT_TIMEPART(msFromTime, 1, msPerSecond)
Marko Mikulicic 0:c0ecb8bf28eb 32551
Marko Mikulicic 0:c0ecb8bf28eb 32552 static int ecma_WeekDay(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32553 int ret = (ecma_Day(t) + 4) % 7;
Marko Mikulicic 0:c0ecb8bf28eb 32554 if (ret < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32555 ret += 7;
Marko Mikulicic 0:c0ecb8bf28eb 32556 }
Marko Mikulicic 0:c0ecb8bf28eb 32557
Marko Mikulicic 0:c0ecb8bf28eb 32558 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 32559 }
Marko Mikulicic 0:c0ecb8bf28eb 32560
Marko Mikulicic 0:c0ecb8bf28eb 32561 static void d_gmtime(const etime_t *t, struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32562 tp->year = ecma_YearFromTime_s(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32563 tp->month = ecma_MonthFromTime(*t, tp->year);
Marko Mikulicic 0:c0ecb8bf28eb 32564 tp->day = ecma_DateFromTime(*t, tp->year);
Marko Mikulicic 0:c0ecb8bf28eb 32565 tp->hour = ecma_HourFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32566 tp->min = ecma_MinFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32567 tp->sec = ecma_SecFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32568 tp->msec = ecma_msFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32569 tp->dayofweek = ecma_WeekDay(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32570 }
Marko Mikulicic 0:c0ecb8bf28eb 32571 #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32572 V7_ENABLE__Date__getters || V7_ENABLE__Date__setters */
Marko Mikulicic 0:c0ecb8bf28eb 32573
Marko Mikulicic 0:c0ecb8bf28eb 32574 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32575 V7_ENABLE__Date__getters || V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 32576 static etimeint_t ecma_LocalTime(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32577 return t + ecma_LocalTZA() + ecma_DaylightSavingTA(t);
Marko Mikulicic 0:c0ecb8bf28eb 32578 }
Marko Mikulicic 0:c0ecb8bf28eb 32579
Marko Mikulicic 0:c0ecb8bf28eb 32580 static void d_localtime(const etime_t *time, struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32581 etime_t local_time = ecma_LocalTime(*time);
Marko Mikulicic 0:c0ecb8bf28eb 32582 d_gmtime(&local_time, tp);
Marko Mikulicic 0:c0ecb8bf28eb 32583 }
Marko Mikulicic 0:c0ecb8bf28eb 32584 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32585
Marko Mikulicic 0:c0ecb8bf28eb 32586 static etimeint_t ecma_MakeTime(etimeint_t hour, etimeint_t min, etimeint_t sec,
Marko Mikulicic 0:c0ecb8bf28eb 32587 etimeint_t ms) {
Marko Mikulicic 0:c0ecb8bf28eb 32588 return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) *
Marko Mikulicic 0:c0ecb8bf28eb 32589 msPerSecond +
Marko Mikulicic 0:c0ecb8bf28eb 32590 ms;
Marko Mikulicic 0:c0ecb8bf28eb 32591 }
Marko Mikulicic 0:c0ecb8bf28eb 32592
Marko Mikulicic 0:c0ecb8bf28eb 32593 static etimeint_t ecma_MakeDay(int year, int month, int date) {
Marko Mikulicic 0:c0ecb8bf28eb 32594 int *days;
Marko Mikulicic 0:c0ecb8bf28eb 32595 etimeint_t yday, mday;
Marko Mikulicic 0:c0ecb8bf28eb 32596
Marko Mikulicic 0:c0ecb8bf28eb 32597 year += floor(month / 12);
Marko Mikulicic 0:c0ecb8bf28eb 32598 month = month % 12;
Marko Mikulicic 0:c0ecb8bf28eb 32599 yday = floor(ecma_TimeFromYear(year) / msPerDay);
Marko Mikulicic 0:c0ecb8bf28eb 32600 days = ecma_getfirstdays(ecma_IsLeapYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32601 mday = days[month];
Marko Mikulicic 0:c0ecb8bf28eb 32602
Marko Mikulicic 0:c0ecb8bf28eb 32603 return yday + mday + date - 1;
Marko Mikulicic 0:c0ecb8bf28eb 32604 }
Marko Mikulicic 0:c0ecb8bf28eb 32605
Marko Mikulicic 0:c0ecb8bf28eb 32606 static etimeint_t ecma_MakeDate(etimeint_t day, etimeint_t time) {
Marko Mikulicic 0:c0ecb8bf28eb 32607 return (day * msPerDay + time);
Marko Mikulicic 0:c0ecb8bf28eb 32608 }
Marko Mikulicic 0:c0ecb8bf28eb 32609
Marko Mikulicic 0:c0ecb8bf28eb 32610 static void d_gettime(etime_t *t) {
Marko Mikulicic 0:c0ecb8bf28eb 32611 #ifndef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 32612 struct timeval tv;
Marko Mikulicic 0:c0ecb8bf28eb 32613 gettimeofday(&tv, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32614 *t = (etime_t) tv.tv_sec * 1000 + (etime_t) tv.tv_usec / 1000;
Marko Mikulicic 0:c0ecb8bf28eb 32615 #else
Marko Mikulicic 0:c0ecb8bf28eb 32616 /* TODO(mkm): use native windows API in order to get ms granularity */
Marko Mikulicic 0:c0ecb8bf28eb 32617 *t = time(NULL) * 1000.0;
Marko Mikulicic 0:c0ecb8bf28eb 32618 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32619 }
Marko Mikulicic 0:c0ecb8bf28eb 32620
Marko Mikulicic 0:c0ecb8bf28eb 32621 static etime_t d_mktime_impl(const struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32622 return ecma_MakeDate(ecma_MakeDay(tp->year, tp->month, tp->day),
Marko Mikulicic 0:c0ecb8bf28eb 32623 ecma_MakeTime(tp->hour, tp->min, tp->sec, tp->msec));
Marko Mikulicic 0:c0ecb8bf28eb 32624 }
Marko Mikulicic 0:c0ecb8bf28eb 32625
Marko Mikulicic 0:c0ecb8bf28eb 32626 #if V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 32627 static etime_t d_lmktime(const struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32628 return ecma_UTC(d_mktime_impl(tp));
Marko Mikulicic 0:c0ecb8bf28eb 32629 }
Marko Mikulicic 0:c0ecb8bf28eb 32630 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32631
Marko Mikulicic 0:c0ecb8bf28eb 32632 static etime_t d_gmktime(const struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32633 return d_mktime_impl(tp);
Marko Mikulicic 0:c0ecb8bf28eb 32634 }
Marko Mikulicic 0:c0ecb8bf28eb 32635
Marko Mikulicic 0:c0ecb8bf28eb 32636 typedef etime_t (*fmaketime_t)(const struct timeparts *);
Marko Mikulicic 0:c0ecb8bf28eb 32637 typedef void (*fbreaktime_t)(const etime_t *, struct timeparts *);
Marko Mikulicic 0:c0ecb8bf28eb 32638
Marko Mikulicic 0:c0ecb8bf28eb 32639 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32640 V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 32641 static val_t d_trytogetobjforstring(struct v7 *v7, val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 32642 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32643 val_t ret = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32644
Marko Mikulicic 0:c0ecb8bf28eb 32645 rcode = obj_value_of(v7, obj, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 32646 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32647 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32648 }
Marko Mikulicic 0:c0ecb8bf28eb 32649
Marko Mikulicic 0:c0ecb8bf28eb 32650 if (ret == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 32651 rcode = v7_throwf(v7, TYPE_ERROR, "Date is invalid (for string)");
Marko Mikulicic 0:c0ecb8bf28eb 32652 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32653 }
Marko Mikulicic 0:c0ecb8bf28eb 32654
Marko Mikulicic 0:c0ecb8bf28eb 32655 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32656 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32657 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 32658 }
Marko Mikulicic 0:c0ecb8bf28eb 32659 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32660
Marko Mikulicic 0:c0ecb8bf28eb 32661 #if V7_ENABLE__Date__parse || V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 32662 static int d_iscalledasfunction(struct v7 *v7, val_t this_obj) {
Marko Mikulicic 0:c0ecb8bf28eb 32663 /* TODO(alashkin): verify this statement */
Marko Mikulicic 0:c0ecb8bf28eb 32664 return is_prototype_of(v7, this_obj, v7->vals.date_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 32665 }
Marko Mikulicic 0:c0ecb8bf28eb 32666 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32667
Marko Mikulicic 0:c0ecb8bf28eb 32668 static const char *mon_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
Marko Mikulicic 0:c0ecb8bf28eb 32669 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Marko Mikulicic 0:c0ecb8bf28eb 32670
Marko Mikulicic 0:c0ecb8bf28eb 32671 int d_getnumbyname(const char **arr, int arr_size, const char *str) {
Marko Mikulicic 0:c0ecb8bf28eb 32672 int i;
Marko Mikulicic 0:c0ecb8bf28eb 32673 for (i = 0; i < arr_size; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32674 if (strncmp(arr[i], str, 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32675 return i + 1;
Marko Mikulicic 0:c0ecb8bf28eb 32676 }
Marko Mikulicic 0:c0ecb8bf28eb 32677 }
Marko Mikulicic 0:c0ecb8bf28eb 32678
Marko Mikulicic 0:c0ecb8bf28eb 32679 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 32680 }
Marko Mikulicic 0:c0ecb8bf28eb 32681
Marko Mikulicic 0:c0ecb8bf28eb 32682 int date_parse(const char *str, int *a1, int *a2, int *a3, char sep,
Marko Mikulicic 0:c0ecb8bf28eb 32683 char *rest) {
Marko Mikulicic 0:c0ecb8bf28eb 32684 char frmDate[] = " %d/%d/%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32685 frmDate[3] = frmDate[6] = sep;
Marko Mikulicic 0:c0ecb8bf28eb 32686 return sscanf(str, frmDate, a1, a2, a3, rest);
Marko Mikulicic 0:c0ecb8bf28eb 32687 }
Marko Mikulicic 0:c0ecb8bf28eb 32688
Marko Mikulicic 0:c0ecb8bf28eb 32689 #define NO_TZ 0x7FFFFFFF
Marko Mikulicic 0:c0ecb8bf28eb 32690
Marko Mikulicic 0:c0ecb8bf28eb 32691 /*
Marko Mikulicic 0:c0ecb8bf28eb 32692 * not very smart but simple, and working according
Marko Mikulicic 0:c0ecb8bf28eb 32693 * to ECMA5.1 StringToDate function
Marko Mikulicic 0:c0ecb8bf28eb 32694 */
Marko Mikulicic 0:c0ecb8bf28eb 32695 static int d_parsedatestr(const char *jstr, size_t len, struct timeparts *tp,
Marko Mikulicic 0:c0ecb8bf28eb 32696 int *tz) {
Marko Mikulicic 0:c0ecb8bf28eb 32697 char gmt[4];
Marko Mikulicic 0:c0ecb8bf28eb 32698 char buf1[100] = {0}, buf2[100] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 32699 int res = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32700 char str[101];
Marko Mikulicic 0:c0ecb8bf28eb 32701 memcpy(str, jstr, len);
Marko Mikulicic 0:c0ecb8bf28eb 32702 str[len] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 32703 memset(tp, 0, sizeof(*tp));
Marko Mikulicic 0:c0ecb8bf28eb 32704 *tz = NO_TZ;
Marko Mikulicic 0:c0ecb8bf28eb 32705
Marko Mikulicic 0:c0ecb8bf28eb 32706 /* trying toISOSrting() format */
Marko Mikulicic 0:c0ecb8bf28eb 32707 {
Marko Mikulicic 0:c0ecb8bf28eb 32708 const char *frmISOString = " %d-%02d-%02dT%02d:%02d:%02d.%03dZ";
Marko Mikulicic 0:c0ecb8bf28eb 32709 res = sscanf(str, frmISOString, &tp->year, &tp->month, &tp->day, &tp->hour,
Marko Mikulicic 0:c0ecb8bf28eb 32710 &tp->min, &tp->sec, &tp->msec);
Marko Mikulicic 0:c0ecb8bf28eb 32711 if (res == 7) {
Marko Mikulicic 0:c0ecb8bf28eb 32712 *tz = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32713 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 32714 }
Marko Mikulicic 0:c0ecb8bf28eb 32715 }
Marko Mikulicic 0:c0ecb8bf28eb 32716
Marko Mikulicic 0:c0ecb8bf28eb 32717 /* trying toString()/toUTCString()/toDateFormat() formats */
Marko Mikulicic 0:c0ecb8bf28eb 32718 {
Marko Mikulicic 0:c0ecb8bf28eb 32719 char month[4];
Marko Mikulicic 0:c0ecb8bf28eb 32720 int dowlen;
Marko Mikulicic 0:c0ecb8bf28eb 32721 const char *frmString = " %*s%n %03s %02d %d %02d:%02d:%02d %03s%d";
Marko Mikulicic 0:c0ecb8bf28eb 32722 res = sscanf(str, frmString, &dowlen, month, &tp->day, &tp->year, &tp->hour,
Marko Mikulicic 0:c0ecb8bf28eb 32723 &tp->min, &tp->sec, gmt, tz);
Marko Mikulicic 0:c0ecb8bf28eb 32724 if ((res == 3 || (res >= 6 && res <= 8)) && dowlen == 3) {
Marko Mikulicic 0:c0ecb8bf28eb 32725 if ((tp->month = d_getnumbyname(mon_name, ARRAY_SIZE(mon_name), month)) !=
Marko Mikulicic 0:c0ecb8bf28eb 32726 -1) {
Marko Mikulicic 0:c0ecb8bf28eb 32727 if (res == 7 && strncmp(gmt, "GMT", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32728 *tz = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32729 }
Marko Mikulicic 0:c0ecb8bf28eb 32730 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 32731 }
Marko Mikulicic 0:c0ecb8bf28eb 32732 }
Marko Mikulicic 0:c0ecb8bf28eb 32733 }
Marko Mikulicic 0:c0ecb8bf28eb 32734
Marko Mikulicic 0:c0ecb8bf28eb 32735 /* trying the rest */
Marko Mikulicic 0:c0ecb8bf28eb 32736
Marko Mikulicic 0:c0ecb8bf28eb 32737 /* trying date */
Marko Mikulicic 0:c0ecb8bf28eb 32738
Marko Mikulicic 0:c0ecb8bf28eb 32739 if (!(date_parse(str, &tp->month, &tp->day, &tp->year, '/', buf1) >= 3 ||
Marko Mikulicic 0:c0ecb8bf28eb 32740 date_parse(str, &tp->day, &tp->month, &tp->year, '.', buf1) >= 3 ||
Marko Mikulicic 0:c0ecb8bf28eb 32741 date_parse(str, &tp->year, &tp->month, &tp->day, '-', buf1) >= 3)) {
Marko Mikulicic 0:c0ecb8bf28eb 32742 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32743 }
Marko Mikulicic 0:c0ecb8bf28eb 32744
Marko Mikulicic 0:c0ecb8bf28eb 32745 /* there is date, trying time; from here return 0 only on errors */
Marko Mikulicic 0:c0ecb8bf28eb 32746
Marko Mikulicic 0:c0ecb8bf28eb 32747 /* trying HH:mm */
Marko Mikulicic 0:c0ecb8bf28eb 32748 {
Marko Mikulicic 0:c0ecb8bf28eb 32749 const char *frmMMhh = " %d:%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32750 res = sscanf(buf1, frmMMhh, &tp->hour, &tp->min, buf2);
Marko Mikulicic 0:c0ecb8bf28eb 32751 /* can't get time, but have some symbols, assuming error */
Marko Mikulicic 0:c0ecb8bf28eb 32752 if (res < 2) {
Marko Mikulicic 0:c0ecb8bf28eb 32753 return (strlen(buf2) == 0);
Marko Mikulicic 0:c0ecb8bf28eb 32754 }
Marko Mikulicic 0:c0ecb8bf28eb 32755 }
Marko Mikulicic 0:c0ecb8bf28eb 32756
Marko Mikulicic 0:c0ecb8bf28eb 32757 /* trying seconds */
Marko Mikulicic 0:c0ecb8bf28eb 32758 {
Marko Mikulicic 0:c0ecb8bf28eb 32759 const char *frmss = ":%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32760 memset(buf1, 0, sizeof(buf1));
Marko Mikulicic 0:c0ecb8bf28eb 32761 res = sscanf(buf2, frmss, &tp->sec, buf1);
Marko Mikulicic 0:c0ecb8bf28eb 32762 }
Marko Mikulicic 0:c0ecb8bf28eb 32763
Marko Mikulicic 0:c0ecb8bf28eb 32764 /* even if we don't get seconds we gonna try to get tz */
Marko Mikulicic 0:c0ecb8bf28eb 32765 {
Marko Mikulicic 0:c0ecb8bf28eb 32766 char *rest = res ? buf1 : buf2;
Marko Mikulicic 0:c0ecb8bf28eb 32767 char *buf = res ? buf2 : buf1;
Marko Mikulicic 0:c0ecb8bf28eb 32768 const char *frmtz = " %03s%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32769
Marko Mikulicic 0:c0ecb8bf28eb 32770 res = sscanf(rest, frmtz, gmt, tz, buf);
Marko Mikulicic 0:c0ecb8bf28eb 32771 if (res == 1 && strncmp(gmt, "GMT", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32772 *tz = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32773 }
Marko Mikulicic 0:c0ecb8bf28eb 32774 }
Marko Mikulicic 0:c0ecb8bf28eb 32775
Marko Mikulicic 0:c0ecb8bf28eb 32776 /* return OK if we are at the end of string */
Marko Mikulicic 0:c0ecb8bf28eb 32777 return res <= 2;
Marko Mikulicic 0:c0ecb8bf28eb 32778 }
Marko Mikulicic 0:c0ecb8bf28eb 32779
Marko Mikulicic 0:c0ecb8bf28eb 32780 static int d_timeFromString(etime_t *time, const char *str, size_t str_len) {
Marko Mikulicic 0:c0ecb8bf28eb 32781 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 32782 int tz;
Marko Mikulicic 0:c0ecb8bf28eb 32783
Marko Mikulicic 0:c0ecb8bf28eb 32784 *time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32785
Marko Mikulicic 0:c0ecb8bf28eb 32786 if (str_len > 100) {
Marko Mikulicic 0:c0ecb8bf28eb 32787 /* too long for valid date string */
Marko Mikulicic 0:c0ecb8bf28eb 32788 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32789 }
Marko Mikulicic 0:c0ecb8bf28eb 32790
Marko Mikulicic 0:c0ecb8bf28eb 32791 if (d_parsedatestr(str, str_len, &tp, &tz)) {
Marko Mikulicic 0:c0ecb8bf28eb 32792 /* check results */
Marko Mikulicic 0:c0ecb8bf28eb 32793 int valid = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32794
Marko Mikulicic 0:c0ecb8bf28eb 32795 tp.month--;
Marko Mikulicic 0:c0ecb8bf28eb 32796 valid = tp.day >= 1 && tp.day <= 31;
Marko Mikulicic 0:c0ecb8bf28eb 32797 valid &= tp.month >= 0 && tp.month <= 11;
Marko Mikulicic 0:c0ecb8bf28eb 32798 valid &= tp.hour >= 0 && tp.hour <= 23;
Marko Mikulicic 0:c0ecb8bf28eb 32799 valid &= tp.min >= 0 && tp.min <= 59;
Marko Mikulicic 0:c0ecb8bf28eb 32800 valid &= tp.sec >= 0 && tp.sec <= 59;
Marko Mikulicic 0:c0ecb8bf28eb 32801
Marko Mikulicic 0:c0ecb8bf28eb 32802 if (tz != NO_TZ && tz > 12) {
Marko Mikulicic 0:c0ecb8bf28eb 32803 tz /= 100;
Marko Mikulicic 0:c0ecb8bf28eb 32804 }
Marko Mikulicic 0:c0ecb8bf28eb 32805
Marko Mikulicic 0:c0ecb8bf28eb 32806 valid &= (abs(tz) <= 12 || tz == NO_TZ);
Marko Mikulicic 0:c0ecb8bf28eb 32807
Marko Mikulicic 0:c0ecb8bf28eb 32808 if (valid) {
Marko Mikulicic 0:c0ecb8bf28eb 32809 *time = d_gmktime(&tp);
Marko Mikulicic 0:c0ecb8bf28eb 32810
Marko Mikulicic 0:c0ecb8bf28eb 32811 if (tz != NO_TZ) {
Marko Mikulicic 0:c0ecb8bf28eb 32812 /* timezone specified, use it */
Marko Mikulicic 0:c0ecb8bf28eb 32813 *time -= (tz * msPerHour);
Marko Mikulicic 0:c0ecb8bf28eb 32814 } else if (tz != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32815 /* assuming local timezone and moving back to UTC */
Marko Mikulicic 0:c0ecb8bf28eb 32816 *time = ecma_UTC(*time);
Marko Mikulicic 0:c0ecb8bf28eb 32817 }
Marko Mikulicic 0:c0ecb8bf28eb 32818 }
Marko Mikulicic 0:c0ecb8bf28eb 32819 }
Marko Mikulicic 0:c0ecb8bf28eb 32820
Marko Mikulicic 0:c0ecb8bf28eb 32821 return !isnan(*time);
Marko Mikulicic 0:c0ecb8bf28eb 32822 }
Marko Mikulicic 0:c0ecb8bf28eb 32823
Marko Mikulicic 0:c0ecb8bf28eb 32824 /* notice: holding month in calendar format (1-12, not 0-11) */
Marko Mikulicic 0:c0ecb8bf28eb 32825 struct dtimepartsarr {
Marko Mikulicic 0:c0ecb8bf28eb 32826 etime_t args[7];
Marko Mikulicic 0:c0ecb8bf28eb 32827 };
Marko Mikulicic 0:c0ecb8bf28eb 32828
Marko Mikulicic 0:c0ecb8bf28eb 32829 enum detimepartsarr {
Marko Mikulicic 0:c0ecb8bf28eb 32830 tpyear = 0,
Marko Mikulicic 0:c0ecb8bf28eb 32831 tpmonth,
Marko Mikulicic 0:c0ecb8bf28eb 32832 tpdate,
Marko Mikulicic 0:c0ecb8bf28eb 32833 tphours,
Marko Mikulicic 0:c0ecb8bf28eb 32834 tpminutes,
Marko Mikulicic 0:c0ecb8bf28eb 32835 tpseconds,
Marko Mikulicic 0:c0ecb8bf28eb 32836 tpmsec,
Marko Mikulicic 0:c0ecb8bf28eb 32837 tpmax
Marko Mikulicic 0:c0ecb8bf28eb 32838 };
Marko Mikulicic 0:c0ecb8bf28eb 32839
Marko Mikulicic 0:c0ecb8bf28eb 32840 static etime_t d_changepartoftime(const etime_t *current,
Marko Mikulicic 0:c0ecb8bf28eb 32841 struct dtimepartsarr *a,
Marko Mikulicic 0:c0ecb8bf28eb 32842 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 32843 fmaketime_t maketimefunc) {
Marko Mikulicic 0:c0ecb8bf28eb 32844 /*
Marko Mikulicic 0:c0ecb8bf28eb 32845 * 0 = year, 1 = month , 2 = date , 3 = hours,
Marko Mikulicic 0:c0ecb8bf28eb 32846 * 4 = minutes, 5 = seconds, 6 = ms
Marko Mikulicic 0:c0ecb8bf28eb 32847 */
Marko Mikulicic 0:c0ecb8bf28eb 32848 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 32849 unsigned long i;
Marko Mikulicic 0:c0ecb8bf28eb 32850 int *tp_arr[7];
Marko Mikulicic 0:c0ecb8bf28eb 32851 /*
Marko Mikulicic 0:c0ecb8bf28eb 32852 * C89 doesn't allow initialization
Marko Mikulicic 0:c0ecb8bf28eb 32853 * like x = {&tp.year, &tp.month, .... }
Marko Mikulicic 0:c0ecb8bf28eb 32854 */
Marko Mikulicic 0:c0ecb8bf28eb 32855 tp_arr[0] = &tp.year;
Marko Mikulicic 0:c0ecb8bf28eb 32856 tp_arr[1] = &tp.month;
Marko Mikulicic 0:c0ecb8bf28eb 32857 tp_arr[2] = &tp.day;
Marko Mikulicic 0:c0ecb8bf28eb 32858 tp_arr[3] = &tp.hour;
Marko Mikulicic 0:c0ecb8bf28eb 32859 tp_arr[4] = &tp.min;
Marko Mikulicic 0:c0ecb8bf28eb 32860 tp_arr[5] = &tp.sec;
Marko Mikulicic 0:c0ecb8bf28eb 32861 tp_arr[6] = &tp.msec;
Marko Mikulicic 0:c0ecb8bf28eb 32862
Marko Mikulicic 0:c0ecb8bf28eb 32863 memset(&tp, 0, sizeof(tp));
Marko Mikulicic 0:c0ecb8bf28eb 32864
Marko Mikulicic 0:c0ecb8bf28eb 32865 if (breaktimefunc != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 32866 breaktimefunc(current, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 32867 }
Marko Mikulicic 0:c0ecb8bf28eb 32868
Marko Mikulicic 0:c0ecb8bf28eb 32869 for (i = 0; i < ARRAY_SIZE(tp_arr); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32870 if (!isnan(a->args[i]) && !isinf(a->args[i])) {
Marko Mikulicic 0:c0ecb8bf28eb 32871 *tp_arr[i] = (int) a->args[i];
Marko Mikulicic 0:c0ecb8bf28eb 32872 }
Marko Mikulicic 0:c0ecb8bf28eb 32873 }
Marko Mikulicic 0:c0ecb8bf28eb 32874
Marko Mikulicic 0:c0ecb8bf28eb 32875 return maketimefunc(&tp);
Marko Mikulicic 0:c0ecb8bf28eb 32876 }
Marko Mikulicic 0:c0ecb8bf28eb 32877
Marko Mikulicic 0:c0ecb8bf28eb 32878 #if V7_ENABLE__Date__setters || V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 32879 static etime_t d_time_number_from_arr(struct v7 *v7, int start_pos,
Marko Mikulicic 0:c0ecb8bf28eb 32880 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 32881 fmaketime_t maketimefunc) {
Marko Mikulicic 0:c0ecb8bf28eb 32882 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32883 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32884 etime_t ret_time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32885 long cargs;
Marko Mikulicic 0:c0ecb8bf28eb 32886
Marko Mikulicic 0:c0ecb8bf28eb 32887 val_t objtime = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32888 rcode = obj_value_of(v7, this_obj, &objtime);
Marko Mikulicic 0:c0ecb8bf28eb 32889 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32890 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32891 }
Marko Mikulicic 0:c0ecb8bf28eb 32892
Marko Mikulicic 0:c0ecb8bf28eb 32893 if ((cargs = v7_argc(v7)) >= 1 && objtime != V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 32894 int i;
Marko Mikulicic 0:c0ecb8bf28eb 32895 etime_t new_part = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32896 struct dtimepartsarr a;
Marko Mikulicic 0:c0ecb8bf28eb 32897 for (i = 0; i < 7; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32898 a.args[i] = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32899 }
Marko Mikulicic 0:c0ecb8bf28eb 32900
Marko Mikulicic 0:c0ecb8bf28eb 32901 for (i = 0; i < cargs && (i + start_pos < tpmax); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32902 {
Marko Mikulicic 0:c0ecb8bf28eb 32903 val_t arg = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 32904 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 32905 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32906 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32907 }
Marko Mikulicic 0:c0ecb8bf28eb 32908 new_part = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 32909 }
Marko Mikulicic 0:c0ecb8bf28eb 32910
Marko Mikulicic 0:c0ecb8bf28eb 32911 if (isnan(new_part)) {
Marko Mikulicic 0:c0ecb8bf28eb 32912 break;
Marko Mikulicic 0:c0ecb8bf28eb 32913 }
Marko Mikulicic 0:c0ecb8bf28eb 32914
Marko Mikulicic 0:c0ecb8bf28eb 32915 a.args[i + start_pos] = new_part;
Marko Mikulicic 0:c0ecb8bf28eb 32916 }
Marko Mikulicic 0:c0ecb8bf28eb 32917
Marko Mikulicic 0:c0ecb8bf28eb 32918 if (!isnan(new_part)) {
Marko Mikulicic 0:c0ecb8bf28eb 32919 etime_t current_time = v7_get_double(v7, objtime);
Marko Mikulicic 0:c0ecb8bf28eb 32920 ret_time =
Marko Mikulicic 0:c0ecb8bf28eb 32921 d_changepartoftime(&current_time, &a, breaktimefunc, maketimefunc);
Marko Mikulicic 0:c0ecb8bf28eb 32922 }
Marko Mikulicic 0:c0ecb8bf28eb 32923 }
Marko Mikulicic 0:c0ecb8bf28eb 32924
Marko Mikulicic 0:c0ecb8bf28eb 32925 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32926 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32927 return ret_time;
Marko Mikulicic 0:c0ecb8bf28eb 32928 }
Marko Mikulicic 0:c0ecb8bf28eb 32929 #endif /* V7_ENABLE__Date__setters */
Marko Mikulicic 0:c0ecb8bf28eb 32930
Marko Mikulicic 0:c0ecb8bf28eb 32931 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 32932 static int d_tptostr(const struct timeparts *tp, char *buf, int addtz);
Marko Mikulicic 0:c0ecb8bf28eb 32933 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32934
Marko Mikulicic 0:c0ecb8bf28eb 32935 /* constructor */
Marko Mikulicic 0:c0ecb8bf28eb 32936 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32937 V7_PRIVATE enum v7_err Date_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32938 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32939 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32940 etime_t ret_time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32941 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 32942 long cargs = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32943 if (cargs <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32944 /* no parameters - return current date & time */
Marko Mikulicic 0:c0ecb8bf28eb 32945 d_gettime(&ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 32946 } else if (cargs == 1) {
Marko Mikulicic 0:c0ecb8bf28eb 32947 /* one parameter */
Marko Mikulicic 0:c0ecb8bf28eb 32948 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 32949 if (v7_is_string(arg)) { /* it could be string */
Marko Mikulicic 0:c0ecb8bf28eb 32950 size_t str_size;
Marko Mikulicic 0:c0ecb8bf28eb 32951 const char *str = v7_get_string(v7, &arg, &str_size);
Marko Mikulicic 0:c0ecb8bf28eb 32952 d_timeFromString(&ret_time, str, str_size);
Marko Mikulicic 0:c0ecb8bf28eb 32953 }
Marko Mikulicic 0:c0ecb8bf28eb 32954 if (isnan(ret_time)) {
Marko Mikulicic 0:c0ecb8bf28eb 32955 /*
Marko Mikulicic 0:c0ecb8bf28eb 32956 * if cannot be parsed or
Marko Mikulicic 0:c0ecb8bf28eb 32957 * not string at all - trying to convert to number
Marko Mikulicic 0:c0ecb8bf28eb 32958 */
Marko Mikulicic 0:c0ecb8bf28eb 32959 ret_time = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32960 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 32961 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32962 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32963 }
Marko Mikulicic 0:c0ecb8bf28eb 32964 ret_time = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 32965 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32966 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32967 }
Marko Mikulicic 0:c0ecb8bf28eb 32968 }
Marko Mikulicic 0:c0ecb8bf28eb 32969 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32970 /* 2+ paramaters - should be parts of a date */
Marko Mikulicic 0:c0ecb8bf28eb 32971 struct dtimepartsarr a;
Marko Mikulicic 0:c0ecb8bf28eb 32972 int i;
Marko Mikulicic 0:c0ecb8bf28eb 32973
Marko Mikulicic 0:c0ecb8bf28eb 32974 memset(&a, 0, sizeof(a));
Marko Mikulicic 0:c0ecb8bf28eb 32975
Marko Mikulicic 0:c0ecb8bf28eb 32976 for (i = 0; i < cargs; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32977 val_t arg = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 32978 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 32979 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32980 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32981 }
Marko Mikulicic 0:c0ecb8bf28eb 32982 a.args[i] = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 32983 if (isnan(a.args[i])) {
Marko Mikulicic 0:c0ecb8bf28eb 32984 break;
Marko Mikulicic 0:c0ecb8bf28eb 32985 }
Marko Mikulicic 0:c0ecb8bf28eb 32986 }
Marko Mikulicic 0:c0ecb8bf28eb 32987
Marko Mikulicic 0:c0ecb8bf28eb 32988 if (i >= cargs) {
Marko Mikulicic 0:c0ecb8bf28eb 32989 /*
Marko Mikulicic 0:c0ecb8bf28eb 32990 * If date is supplied then let
Marko Mikulicic 0:c0ecb8bf28eb 32991 * dt be ToNumber(date); else let dt be 1.
Marko Mikulicic 0:c0ecb8bf28eb 32992 */
Marko Mikulicic 0:c0ecb8bf28eb 32993 if (a.args[tpdate] == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32994 a.args[tpdate] = 1;
Marko Mikulicic 0:c0ecb8bf28eb 32995 }
Marko Mikulicic 0:c0ecb8bf28eb 32996
Marko Mikulicic 0:c0ecb8bf28eb 32997 if (a.args[tpyear] >= 0 && a.args[tpyear] <= 99) {
Marko Mikulicic 0:c0ecb8bf28eb 32998 /*
Marko Mikulicic 0:c0ecb8bf28eb 32999 * If y is not NaN and 0 <= ToInteger(y) <= 99,
Marko Mikulicic 0:c0ecb8bf28eb 33000 * then let yr be 1900+ToInteger(y); otherwise, let yr be y.
Marko Mikulicic 0:c0ecb8bf28eb 33001 */
Marko Mikulicic 0:c0ecb8bf28eb 33002 a.args[tpyear] += 1900;
Marko Mikulicic 0:c0ecb8bf28eb 33003 }
Marko Mikulicic 0:c0ecb8bf28eb 33004
Marko Mikulicic 0:c0ecb8bf28eb 33005 ret_time = ecma_UTC(d_changepartoftime(0, &a, 0, d_gmktime));
Marko Mikulicic 0:c0ecb8bf28eb 33006 }
Marko Mikulicic 0:c0ecb8bf28eb 33007 }
Marko Mikulicic 0:c0ecb8bf28eb 33008
Marko Mikulicic 0:c0ecb8bf28eb 33009 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 33010 get_object_struct(v7->vals.date_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 33011
Marko Mikulicic 0:c0ecb8bf28eb 33012 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_number(v7, ret_time));
Marko Mikulicic 0:c0ecb8bf28eb 33013 /*
Marko Mikulicic 0:c0ecb8bf28eb 33014 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 33015 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 33016 */
Marko Mikulicic 0:c0ecb8bf28eb 33017 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33018 } else {
Marko Mikulicic 0:c0ecb8bf28eb 33019 /*
Marko Mikulicic 0:c0ecb8bf28eb 33020 * according to 15.9.2.1 we should ignore all
Marko Mikulicic 0:c0ecb8bf28eb 33021 * parameters in case of function-call
Marko Mikulicic 0:c0ecb8bf28eb 33022 */
Marko Mikulicic 0:c0ecb8bf28eb 33023 char buf[50];
Marko Mikulicic 0:c0ecb8bf28eb 33024 int len;
Marko Mikulicic 0:c0ecb8bf28eb 33025
Marko Mikulicic 0:c0ecb8bf28eb 33026 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 33027 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 33028 d_gettime(&ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33029 d_localtime(&ret_time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 33030 len = d_tptostr(&tp, buf, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33031 #else
Marko Mikulicic 0:c0ecb8bf28eb 33032 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33033 #endif /* V7_ENABLE__Date__toString */
Marko Mikulicic 0:c0ecb8bf28eb 33034
Marko Mikulicic 0:c0ecb8bf28eb 33035 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33036 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33037 }
Marko Mikulicic 0:c0ecb8bf28eb 33038
Marko Mikulicic 0:c0ecb8bf28eb 33039 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33040 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33041 }
Marko Mikulicic 0:c0ecb8bf28eb 33042
Marko Mikulicic 0:c0ecb8bf28eb 33043 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 33044 static int d_timetoISOstr(const etime_t *time, char *buf, size_t buf_size) {
Marko Mikulicic 0:c0ecb8bf28eb 33045 /* ISO format: "+XXYYYY-MM-DDTHH:mm:ss.sssZ"; */
Marko Mikulicic 0:c0ecb8bf28eb 33046 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 33047 char use_ext = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33048 const char *ey_frm = "%06d-%02d-%02dT%02d:%02d:%02d.%03dZ";
Marko Mikulicic 0:c0ecb8bf28eb 33049 const char *simpl_frm = "%d-%02d-%02dT%02d:%02d:%02d.%03dZ";
Marko Mikulicic 0:c0ecb8bf28eb 33050
Marko Mikulicic 0:c0ecb8bf28eb 33051 d_gmtime(time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 33052
Marko Mikulicic 0:c0ecb8bf28eb 33053 if (abs(tp.year) > 9999 || tp.year < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33054 *buf = (tp.year > 0) ? '+' : '-';
Marko Mikulicic 0:c0ecb8bf28eb 33055 use_ext = 1;
Marko Mikulicic 0:c0ecb8bf28eb 33056 }
Marko Mikulicic 0:c0ecb8bf28eb 33057
Marko Mikulicic 0:c0ecb8bf28eb 33058 return c_snprintf(buf + use_ext, buf_size - use_ext,
Marko Mikulicic 0:c0ecb8bf28eb 33059 use_ext ? ey_frm : simpl_frm, abs(tp.year), tp.month + 1,
Marko Mikulicic 0:c0ecb8bf28eb 33060 tp.day, tp.hour, tp.min, tp.sec, tp.msec) +
Marko Mikulicic 0:c0ecb8bf28eb 33061 use_ext;
Marko Mikulicic 0:c0ecb8bf28eb 33062 }
Marko Mikulicic 0:c0ecb8bf28eb 33063
Marko Mikulicic 0:c0ecb8bf28eb 33064 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33065 V7_PRIVATE enum v7_err Date_toISOString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33066 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33067 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33068 char buf[30];
Marko Mikulicic 0:c0ecb8bf28eb 33069 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33070 int len;
Marko Mikulicic 0:c0ecb8bf28eb 33071
Marko Mikulicic 0:c0ecb8bf28eb 33072 if (val_type(v7, this_obj) != V7_TYPE_DATE_OBJECT) {
Marko Mikulicic 0:c0ecb8bf28eb 33073 rcode = v7_throwf(v7, TYPE_ERROR, "This is not a Date object");
Marko Mikulicic 0:c0ecb8bf28eb 33074 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33075 }
Marko Mikulicic 0:c0ecb8bf28eb 33076
Marko Mikulicic 0:c0ecb8bf28eb 33077 time = v7_get_double(v7, d_trytogetobjforstring(v7, this_obj));
Marko Mikulicic 0:c0ecb8bf28eb 33078 len = d_timetoISOstr(&time, buf, sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 33079 if (len > (int) (sizeof(buf) - 1 /*null-term*/)) {
Marko Mikulicic 0:c0ecb8bf28eb 33080 len = (int) (sizeof(buf) - 1 /*null-term*/);
Marko Mikulicic 0:c0ecb8bf28eb 33081 }
Marko Mikulicic 0:c0ecb8bf28eb 33082
Marko Mikulicic 0:c0ecb8bf28eb 33083 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33084
Marko Mikulicic 0:c0ecb8bf28eb 33085 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33086 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33087 }
Marko Mikulicic 0:c0ecb8bf28eb 33088 #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON */
Marko Mikulicic 0:c0ecb8bf28eb 33089
Marko Mikulicic 0:c0ecb8bf28eb 33090 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 33091 typedef int (*ftostring_t)(const struct timeparts *, char *, int);
Marko Mikulicic 0:c0ecb8bf28eb 33092
Marko Mikulicic 0:c0ecb8bf28eb 33093 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33094 static enum v7_err d_tostring(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 33095 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 33096 ftostring_t tostringfunc, int addtz,
Marko Mikulicic 0:c0ecb8bf28eb 33097 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33098 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33099 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 33100 int len;
Marko Mikulicic 0:c0ecb8bf28eb 33101 char buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 33102 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33103
Marko Mikulicic 0:c0ecb8bf28eb 33104 time = v7_get_double(v7, d_trytogetobjforstring(v7, obj));
Marko Mikulicic 0:c0ecb8bf28eb 33105
Marko Mikulicic 0:c0ecb8bf28eb 33106 breaktimefunc(&time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 33107 len = tostringfunc(&tp, buf, addtz);
Marko Mikulicic 0:c0ecb8bf28eb 33108
Marko Mikulicic 0:c0ecb8bf28eb 33109 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33110 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33111 }
Marko Mikulicic 0:c0ecb8bf28eb 33112
Marko Mikulicic 0:c0ecb8bf28eb 33113 /* using macros to avoid copy-paste technic */
Marko Mikulicic 0:c0ecb8bf28eb 33114 #define DEF_TOSTR(funcname, breaktimefunc, tostrfunc, addtz) \
Marko Mikulicic 0:c0ecb8bf28eb 33115 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33116 V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33117 val_t this_obj = v7_get_this(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 33118 return d_tostring(v7, this_obj, breaktimefunc, tostrfunc, addtz, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33119 }
Marko Mikulicic 0:c0ecb8bf28eb 33120
Marko Mikulicic 0:c0ecb8bf28eb 33121 /* non-locale function should always return in english and 24h-format */
Marko Mikulicic 0:c0ecb8bf28eb 33122 static const char *wday_name[] = {"Sun", "Mon", "Tue", "Wed",
Marko Mikulicic 0:c0ecb8bf28eb 33123 "Thu", "Fri", "Sat"};
Marko Mikulicic 0:c0ecb8bf28eb 33124
Marko Mikulicic 0:c0ecb8bf28eb 33125 static int d_tptodatestr(const struct timeparts *tp, char *buf, int addtz) {
Marko Mikulicic 0:c0ecb8bf28eb 33126 (void) addtz;
Marko Mikulicic 0:c0ecb8bf28eb 33127
Marko Mikulicic 0:c0ecb8bf28eb 33128 return sprintf(buf, "%s %s %02d %d", wday_name[tp->dayofweek],
Marko Mikulicic 0:c0ecb8bf28eb 33129 mon_name[tp->month], tp->day, tp->year);
Marko Mikulicic 0:c0ecb8bf28eb 33130 }
Marko Mikulicic 0:c0ecb8bf28eb 33131
Marko Mikulicic 0:c0ecb8bf28eb 33132 DEF_TOSTR(DateString, d_localtime, d_tptodatestr, 1)
Marko Mikulicic 0:c0ecb8bf28eb 33133
Marko Mikulicic 0:c0ecb8bf28eb 33134 static const char *d_gettzname(void) {
Marko Mikulicic 0:c0ecb8bf28eb 33135 return g_tzname;
Marko Mikulicic 0:c0ecb8bf28eb 33136 }
Marko Mikulicic 0:c0ecb8bf28eb 33137
Marko Mikulicic 0:c0ecb8bf28eb 33138 static int d_tptotimestr(const struct timeparts *tp, char *buf, int addtz) {
Marko Mikulicic 0:c0ecb8bf28eb 33139 int len;
Marko Mikulicic 0:c0ecb8bf28eb 33140
Marko Mikulicic 0:c0ecb8bf28eb 33141 len = sprintf(buf, "%02d:%02d:%02d GMT", tp->hour, tp->min, tp->sec);
Marko Mikulicic 0:c0ecb8bf28eb 33142
Marko Mikulicic 0:c0ecb8bf28eb 33143 if (addtz && g_gmtoffms != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33144 len = sprintf(buf + len, "%c%02d00 (%s)", g_gmtoffms > 0 ? '-' : '+',
Marko Mikulicic 0:c0ecb8bf28eb 33145 abs((int) g_gmtoffms / msPerHour), d_gettzname());
Marko Mikulicic 0:c0ecb8bf28eb 33146 }
Marko Mikulicic 0:c0ecb8bf28eb 33147
Marko Mikulicic 0:c0ecb8bf28eb 33148 return (int) strlen(buf);
Marko Mikulicic 0:c0ecb8bf28eb 33149 }
Marko Mikulicic 0:c0ecb8bf28eb 33150
Marko Mikulicic 0:c0ecb8bf28eb 33151 DEF_TOSTR(TimeString, d_localtime, d_tptotimestr, 1)
Marko Mikulicic 0:c0ecb8bf28eb 33152
Marko Mikulicic 0:c0ecb8bf28eb 33153 static int d_tptostr(const struct timeparts *tp, char *buf, int addtz) {
Marko Mikulicic 0:c0ecb8bf28eb 33154 int len = d_tptodatestr(tp, buf, addtz);
Marko Mikulicic 0:c0ecb8bf28eb 33155 *(buf + len) = ' ';
Marko Mikulicic 0:c0ecb8bf28eb 33156 return d_tptotimestr(tp, buf + len + 1, addtz) + len + 1;
Marko Mikulicic 0:c0ecb8bf28eb 33157 }
Marko Mikulicic 0:c0ecb8bf28eb 33158
Marko Mikulicic 0:c0ecb8bf28eb 33159 DEF_TOSTR(String, d_localtime, d_tptostr, 1)
Marko Mikulicic 0:c0ecb8bf28eb 33160 DEF_TOSTR(UTCString, d_gmtime, d_tptostr, 0)
Marko Mikulicic 0:c0ecb8bf28eb 33161 #endif /* V7_ENABLE__Date__toString */
Marko Mikulicic 0:c0ecb8bf28eb 33162
Marko Mikulicic 0:c0ecb8bf28eb 33163 #if V7_ENABLE__Date__toLocaleString
Marko Mikulicic 0:c0ecb8bf28eb 33164 struct d_locale {
Marko Mikulicic 0:c0ecb8bf28eb 33165 char locale[50];
Marko Mikulicic 0:c0ecb8bf28eb 33166 };
Marko Mikulicic 0:c0ecb8bf28eb 33167
Marko Mikulicic 0:c0ecb8bf28eb 33168 static void d_getcurrentlocale(struct d_locale *loc) {
Marko Mikulicic 0:c0ecb8bf28eb 33169 strcpy(loc->locale, setlocale(LC_TIME, 0));
Marko Mikulicic 0:c0ecb8bf28eb 33170 }
Marko Mikulicic 0:c0ecb8bf28eb 33171
Marko Mikulicic 0:c0ecb8bf28eb 33172 static void d_setlocale(const struct d_locale *loc) {
Marko Mikulicic 0:c0ecb8bf28eb 33173 setlocale(LC_TIME, loc ? loc->locale : "");
Marko Mikulicic 0:c0ecb8bf28eb 33174 }
Marko Mikulicic 0:c0ecb8bf28eb 33175
Marko Mikulicic 0:c0ecb8bf28eb 33176 /* TODO(alashkin): check portability */
Marko Mikulicic 0:c0ecb8bf28eb 33177 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33178 static enum v7_err d_tolocalestr(struct v7 *v7, val_t obj, const char *frm,
Marko Mikulicic 0:c0ecb8bf28eb 33179 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33180 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33181 char buf[250];
Marko Mikulicic 0:c0ecb8bf28eb 33182 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 33183 struct tm t;
Marko Mikulicic 0:c0ecb8bf28eb 33184 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33185 struct d_locale prev_locale;
Marko Mikulicic 0:c0ecb8bf28eb 33186 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 33187
Marko Mikulicic 0:c0ecb8bf28eb 33188 time = v7_get_double(v7, d_trytogetobjforstring(v7, obj));
Marko Mikulicic 0:c0ecb8bf28eb 33189
Marko Mikulicic 0:c0ecb8bf28eb 33190 d_getcurrentlocale(&prev_locale);
Marko Mikulicic 0:c0ecb8bf28eb 33191 d_setlocale(0);
Marko Mikulicic 0:c0ecb8bf28eb 33192 d_localtime(&time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 33193
Marko Mikulicic 0:c0ecb8bf28eb 33194 memset(&t, 0, sizeof(t));
Marko Mikulicic 0:c0ecb8bf28eb 33195 t.tm_year = tp.year - 1900;
Marko Mikulicic 0:c0ecb8bf28eb 33196 t.tm_mon = tp.month;
Marko Mikulicic 0:c0ecb8bf28eb 33197 t.tm_mday = tp.day;
Marko Mikulicic 0:c0ecb8bf28eb 33198 t.tm_hour = tp.hour;
Marko Mikulicic 0:c0ecb8bf28eb 33199 t.tm_min = tp.min;
Marko Mikulicic 0:c0ecb8bf28eb 33200 t.tm_sec = tp.sec;
Marko Mikulicic 0:c0ecb8bf28eb 33201 t.tm_wday = tp.dayofweek;
Marko Mikulicic 0:c0ecb8bf28eb 33202
Marko Mikulicic 0:c0ecb8bf28eb 33203 len = strftime(buf, sizeof(buf), frm, &t);
Marko Mikulicic 0:c0ecb8bf28eb 33204
Marko Mikulicic 0:c0ecb8bf28eb 33205 d_setlocale(&prev_locale);
Marko Mikulicic 0:c0ecb8bf28eb 33206
Marko Mikulicic 0:c0ecb8bf28eb 33207 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33208 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33209 }
Marko Mikulicic 0:c0ecb8bf28eb 33210
Marko Mikulicic 0:c0ecb8bf28eb 33211 #define DEF_TOLOCALESTR(funcname, frm) \
Marko Mikulicic 0:c0ecb8bf28eb 33212 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33213 V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33214 val_t this_obj = v7_get_this(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 33215 return d_tolocalestr(v7, this_obj, frm, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33216 }
Marko Mikulicic 0:c0ecb8bf28eb 33217
Marko Mikulicic 0:c0ecb8bf28eb 33218 DEF_TOLOCALESTR(LocaleString, "%c")
Marko Mikulicic 0:c0ecb8bf28eb 33219 DEF_TOLOCALESTR(LocaleDateString, "%x")
Marko Mikulicic 0:c0ecb8bf28eb 33220 DEF_TOLOCALESTR(LocaleTimeString, "%X")
Marko Mikulicic 0:c0ecb8bf28eb 33221 #endif /* V7_ENABLE__Date__toLocaleString */
Marko Mikulicic 0:c0ecb8bf28eb 33222
Marko Mikulicic 0:c0ecb8bf28eb 33223 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33224 V7_PRIVATE enum v7_err Date_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33225 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33226 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33227 if (!v7_is_generic_object(this_obj) ||
Marko Mikulicic 0:c0ecb8bf28eb 33228 (v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 33229 v7_get_proto(v7, this_obj) != v7->vals.date_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 33230 rcode = v7_throwf(v7, TYPE_ERROR, "Date.valueOf called on non-Date object");
Marko Mikulicic 0:c0ecb8bf28eb 33231 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33232 }
Marko Mikulicic 0:c0ecb8bf28eb 33233
Marko Mikulicic 0:c0ecb8bf28eb 33234 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 33235 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33236 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33237 }
Marko Mikulicic 0:c0ecb8bf28eb 33238
Marko Mikulicic 0:c0ecb8bf28eb 33239 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33240 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33241 }
Marko Mikulicic 0:c0ecb8bf28eb 33242
Marko Mikulicic 0:c0ecb8bf28eb 33243 #if V7_ENABLE__Date__getters
Marko Mikulicic 0:c0ecb8bf28eb 33244 static struct timeparts *d_getTimePart(struct v7 *v7, val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 33245 struct timeparts *tp,
Marko Mikulicic 0:c0ecb8bf28eb 33246 fbreaktime_t breaktimefunc) {
Marko Mikulicic 0:c0ecb8bf28eb 33247 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33248 time = v7_get_double(v7, val);
Marko Mikulicic 0:c0ecb8bf28eb 33249 breaktimefunc(&time, tp);
Marko Mikulicic 0:c0ecb8bf28eb 33250 return tp;
Marko Mikulicic 0:c0ecb8bf28eb 33251 }
Marko Mikulicic 0:c0ecb8bf28eb 33252
Marko Mikulicic 0:c0ecb8bf28eb 33253 #define DEF_GET_TP_FUNC(funcName, tpmember, breaktimefunc) \
Marko Mikulicic 0:c0ecb8bf28eb 33254 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33255 V7_PRIVATE enum v7_err Date_get##funcName(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33256 enum v7_err rcode = V7_OK; \
Marko Mikulicic 0:c0ecb8bf28eb 33257 val_t v = V7_UNDEFINED; \
Marko Mikulicic 0:c0ecb8bf28eb 33258 struct timeparts tp; \
Marko Mikulicic 0:c0ecb8bf28eb 33259 val_t this_obj = v7_get_this(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 33260 \
Marko Mikulicic 0:c0ecb8bf28eb 33261 rcode = obj_value_of(v7, this_obj, &v); \
Marko Mikulicic 0:c0ecb8bf28eb 33262 if (rcode != V7_OK) { \
Marko Mikulicic 0:c0ecb8bf28eb 33263 goto clean; \
Marko Mikulicic 0:c0ecb8bf28eb 33264 } \
Marko Mikulicic 0:c0ecb8bf28eb 33265 *res = v7_mk_number( \
Marko Mikulicic 0:c0ecb8bf28eb 33266 v7, v == V7_TAG_NAN ? NAN : d_getTimePart(v7, v, &tp, breaktimefunc) \
Marko Mikulicic 0:c0ecb8bf28eb 33267 ->tpmember); \
Marko Mikulicic 0:c0ecb8bf28eb 33268 clean: \
Marko Mikulicic 0:c0ecb8bf28eb 33269 return rcode; \
Marko Mikulicic 0:c0ecb8bf28eb 33270 }
Marko Mikulicic 0:c0ecb8bf28eb 33271
Marko Mikulicic 0:c0ecb8bf28eb 33272 #define DEF_GET_TP(funcName, tpmember) \
Marko Mikulicic 0:c0ecb8bf28eb 33273 DEF_GET_TP_FUNC(UTC##funcName, tpmember, d_gmtime) \
Marko Mikulicic 0:c0ecb8bf28eb 33274 DEF_GET_TP_FUNC(funcName, tpmember, d_localtime)
Marko Mikulicic 0:c0ecb8bf28eb 33275
Marko Mikulicic 0:c0ecb8bf28eb 33276 DEF_GET_TP(Date, day)
Marko Mikulicic 0:c0ecb8bf28eb 33277 DEF_GET_TP(FullYear, year)
Marko Mikulicic 0:c0ecb8bf28eb 33278 DEF_GET_TP(Month, month)
Marko Mikulicic 0:c0ecb8bf28eb 33279 DEF_GET_TP(Hours, hour)
Marko Mikulicic 0:c0ecb8bf28eb 33280 DEF_GET_TP(Minutes, min)
Marko Mikulicic 0:c0ecb8bf28eb 33281 DEF_GET_TP(Seconds, sec)
Marko Mikulicic 0:c0ecb8bf28eb 33282 DEF_GET_TP(Milliseconds, msec)
Marko Mikulicic 0:c0ecb8bf28eb 33283 DEF_GET_TP(Day, dayofweek)
Marko Mikulicic 0:c0ecb8bf28eb 33284
Marko Mikulicic 0:c0ecb8bf28eb 33285 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33286 V7_PRIVATE enum v7_err Date_getTime(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33287 return Date_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 33288 }
Marko Mikulicic 0:c0ecb8bf28eb 33289
Marko Mikulicic 0:c0ecb8bf28eb 33290 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33291 V7_PRIVATE enum v7_err Date_getTimezoneOffset(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33292 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 33293 *res = v7_mk_number(v7, g_gmtoffms / msPerMinute);
Marko Mikulicic 0:c0ecb8bf28eb 33294 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33295 }
Marko Mikulicic 0:c0ecb8bf28eb 33296 #endif /* V7_ENABLE__Date__getters */
Marko Mikulicic 0:c0ecb8bf28eb 33297
Marko Mikulicic 0:c0ecb8bf28eb 33298 #if V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 33299 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33300 static enum v7_err d_setTimePart(struct v7 *v7, int start_pos,
Marko Mikulicic 0:c0ecb8bf28eb 33301 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 33302 fmaketime_t maketimefunc, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33303 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33304 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33305 etime_t ret_time =
Marko Mikulicic 0:c0ecb8bf28eb 33306 d_time_number_from_arr(v7, start_pos, breaktimefunc, maketimefunc);
Marko Mikulicic 0:c0ecb8bf28eb 33307
Marko Mikulicic 0:c0ecb8bf28eb 33308 *res = v7_mk_number(v7, ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33309 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 33310
Marko Mikulicic 0:c0ecb8bf28eb 33311 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33312 }
Marko Mikulicic 0:c0ecb8bf28eb 33313
Marko Mikulicic 0:c0ecb8bf28eb 33314 #define DEF_SET_TP(name, start_pos) \
Marko Mikulicic 0:c0ecb8bf28eb 33315 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33316 V7_PRIVATE enum v7_err Date_setUTC##name(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33317 return d_setTimePart(v7, start_pos, d_gmtime, d_gmktime, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33318 } \
Marko Mikulicic 0:c0ecb8bf28eb 33319 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33320 V7_PRIVATE enum v7_err Date_set##name(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33321 return d_setTimePart(v7, start_pos, d_localtime, d_lmktime, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33322 }
Marko Mikulicic 0:c0ecb8bf28eb 33323
Marko Mikulicic 0:c0ecb8bf28eb 33324 DEF_SET_TP(Milliseconds, tpmsec)
Marko Mikulicic 0:c0ecb8bf28eb 33325 DEF_SET_TP(Seconds, tpseconds)
Marko Mikulicic 0:c0ecb8bf28eb 33326 DEF_SET_TP(Minutes, tpminutes)
Marko Mikulicic 0:c0ecb8bf28eb 33327 DEF_SET_TP(Hours, tphours)
Marko Mikulicic 0:c0ecb8bf28eb 33328 DEF_SET_TP(Date, tpdate)
Marko Mikulicic 0:c0ecb8bf28eb 33329 DEF_SET_TP(Month, tpmonth)
Marko Mikulicic 0:c0ecb8bf28eb 33330 DEF_SET_TP(FullYear, tpyear)
Marko Mikulicic 0:c0ecb8bf28eb 33331
Marko Mikulicic 0:c0ecb8bf28eb 33332 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33333 V7_PRIVATE enum v7_err Date_setTime(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33334 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33335 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33336
Marko Mikulicic 0:c0ecb8bf28eb 33337 if (v7_argc(v7) >= 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33338 rcode = to_number_v(v7, v7_arg(v7, 0), res);
Marko Mikulicic 0:c0ecb8bf28eb 33339 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33340 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33341 }
Marko Mikulicic 0:c0ecb8bf28eb 33342 }
Marko Mikulicic 0:c0ecb8bf28eb 33343
Marko Mikulicic 0:c0ecb8bf28eb 33344 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 33345
Marko Mikulicic 0:c0ecb8bf28eb 33346 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33347 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33348 }
Marko Mikulicic 0:c0ecb8bf28eb 33349 #endif /* V7_ENABLE__Date__setters */
Marko Mikulicic 0:c0ecb8bf28eb 33350
Marko Mikulicic 0:c0ecb8bf28eb 33351 #if V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 33352 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33353 V7_PRIVATE enum v7_err Date_toJSON(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33354 return Date_toISOString(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 33355 }
Marko Mikulicic 0:c0ecb8bf28eb 33356 #endif /* V7_ENABLE__Date__toJSON */
Marko Mikulicic 0:c0ecb8bf28eb 33357
Marko Mikulicic 0:c0ecb8bf28eb 33358 #if V7_ENABLE__Date__now
Marko Mikulicic 0:c0ecb8bf28eb 33359 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33360 V7_PRIVATE enum v7_err Date_now(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33361 etime_t ret_time;
Marko Mikulicic 0:c0ecb8bf28eb 33362 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 33363
Marko Mikulicic 0:c0ecb8bf28eb 33364 d_gettime(&ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33365
Marko Mikulicic 0:c0ecb8bf28eb 33366 *res = v7_mk_number(v7, ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33367 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33368 }
Marko Mikulicic 0:c0ecb8bf28eb 33369 #endif /* V7_ENABLE__Date__now */
Marko Mikulicic 0:c0ecb8bf28eb 33370
Marko Mikulicic 0:c0ecb8bf28eb 33371 #if V7_ENABLE__Date__parse
Marko Mikulicic 0:c0ecb8bf28eb 33372 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33373 V7_PRIVATE enum v7_err Date_parse(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33374 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33375 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33376 etime_t ret_time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 33377
Marko Mikulicic 0:c0ecb8bf28eb 33378 if (!d_iscalledasfunction(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33379 rcode = v7_throwf(v7, TYPE_ERROR, "Date.parse() called on object");
Marko Mikulicic 0:c0ecb8bf28eb 33380 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33381 }
Marko Mikulicic 0:c0ecb8bf28eb 33382
Marko Mikulicic 0:c0ecb8bf28eb 33383 if (v7_argc(v7) >= 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33384 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33385 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 33386 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 33387 const char *time_str = v7_get_string(v7, &arg0, &size);
Marko Mikulicic 0:c0ecb8bf28eb 33388
Marko Mikulicic 0:c0ecb8bf28eb 33389 d_timeFromString(&ret_time, time_str, size);
Marko Mikulicic 0:c0ecb8bf28eb 33390 }
Marko Mikulicic 0:c0ecb8bf28eb 33391 }
Marko Mikulicic 0:c0ecb8bf28eb 33392
Marko Mikulicic 0:c0ecb8bf28eb 33393 *res = v7_mk_number(v7, ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33394
Marko Mikulicic 0:c0ecb8bf28eb 33395 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33396 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33397 }
Marko Mikulicic 0:c0ecb8bf28eb 33398 #endif /* V7_ENABLE__Date__parse */
Marko Mikulicic 0:c0ecb8bf28eb 33399
Marko Mikulicic 0:c0ecb8bf28eb 33400 #if V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 33401 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33402 V7_PRIVATE enum v7_err Date_UTC(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33403 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33404 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33405 etime_t ret_time;
Marko Mikulicic 0:c0ecb8bf28eb 33406
Marko Mikulicic 0:c0ecb8bf28eb 33407 if (!d_iscalledasfunction(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33408 rcode = v7_throwf(v7, TYPE_ERROR, "Date.now() called on object");
Marko Mikulicic 0:c0ecb8bf28eb 33409 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33410 }
Marko Mikulicic 0:c0ecb8bf28eb 33411
Marko Mikulicic 0:c0ecb8bf28eb 33412 ret_time = d_time_number_from_arr(v7, tpyear, 0, d_gmktime);
Marko Mikulicic 0:c0ecb8bf28eb 33413 *res = v7_mk_number(v7, ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33414
Marko Mikulicic 0:c0ecb8bf28eb 33415 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33416 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33417 }
Marko Mikulicic 0:c0ecb8bf28eb 33418 #endif /* V7_ENABLE__Date__UTC */
Marko Mikulicic 0:c0ecb8bf28eb 33419
Marko Mikulicic 0:c0ecb8bf28eb 33420 /****** Initialization *******/
Marko Mikulicic 0:c0ecb8bf28eb 33421
Marko Mikulicic 0:c0ecb8bf28eb 33422 /*
Marko Mikulicic 0:c0ecb8bf28eb 33423 * We should clear V7_PROPERTY_ENUMERABLE for all Date props
Marko Mikulicic 0:c0ecb8bf28eb 33424 * TODO(mkm): check other objects
Marko Mikulicic 0:c0ecb8bf28eb 33425 */
Marko Mikulicic 0:c0ecb8bf28eb 33426 static int d_set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 33427 v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 33428 return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 33429 v7_mk_cfunction(f));
Marko Mikulicic 0:c0ecb8bf28eb 33430 }
Marko Mikulicic 0:c0ecb8bf28eb 33431
Marko Mikulicic 0:c0ecb8bf28eb 33432 #define DECLARE_GET(func) \
Marko Mikulicic 0:c0ecb8bf28eb 33433 d_set_cfunc_prop(v7, v7->vals.date_prototype, "getUTC" #func, \
Marko Mikulicic 0:c0ecb8bf28eb 33434 Date_getUTC##func); \
Marko Mikulicic 0:c0ecb8bf28eb 33435 d_set_cfunc_prop(v7, v7->vals.date_prototype, "get" #func, Date_get##func);
Marko Mikulicic 0:c0ecb8bf28eb 33436
Marko Mikulicic 0:c0ecb8bf28eb 33437 #define DECLARE_SET(func) \
Marko Mikulicic 0:c0ecb8bf28eb 33438 d_set_cfunc_prop(v7, v7->vals.date_prototype, "setUTC" #func, \
Marko Mikulicic 0:c0ecb8bf28eb 33439 Date_setUTC##func); \
Marko Mikulicic 0:c0ecb8bf28eb 33440 d_set_cfunc_prop(v7, v7->vals.date_prototype, "set" #func, Date_set##func);
Marko Mikulicic 0:c0ecb8bf28eb 33441
Marko Mikulicic 0:c0ecb8bf28eb 33442 V7_PRIVATE void init_date(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 33443 val_t date =
Marko Mikulicic 0:c0ecb8bf28eb 33444 mk_cfunction_obj_with_proto(v7, Date_ctor, 7, v7->vals.date_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 33445 v7_def(v7, v7->vals.global_object, "Date", 4, V7_DESC_ENUMERABLE(0), date);
Marko Mikulicic 0:c0ecb8bf28eb 33446 d_set_cfunc_prop(v7, v7->vals.date_prototype, "valueOf", Date_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 33447
Marko Mikulicic 0:c0ecb8bf28eb 33448 #if V7_ENABLE__Date__getters
Marko Mikulicic 0:c0ecb8bf28eb 33449 DECLARE_GET(Date);
Marko Mikulicic 0:c0ecb8bf28eb 33450 DECLARE_GET(FullYear);
Marko Mikulicic 0:c0ecb8bf28eb 33451 DECLARE_GET(Month);
Marko Mikulicic 0:c0ecb8bf28eb 33452 DECLARE_GET(Hours);
Marko Mikulicic 0:c0ecb8bf28eb 33453 DECLARE_GET(Minutes);
Marko Mikulicic 0:c0ecb8bf28eb 33454 DECLARE_GET(Seconds);
Marko Mikulicic 0:c0ecb8bf28eb 33455 DECLARE_GET(Milliseconds);
Marko Mikulicic 0:c0ecb8bf28eb 33456 DECLARE_GET(Day);
Marko Mikulicic 0:c0ecb8bf28eb 33457 d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTime", Date_getTime);
Marko Mikulicic 0:c0ecb8bf28eb 33458 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33459
Marko Mikulicic 0:c0ecb8bf28eb 33460 #if V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 33461 DECLARE_SET(Date);
Marko Mikulicic 0:c0ecb8bf28eb 33462 DECLARE_SET(FullYear);
Marko Mikulicic 0:c0ecb8bf28eb 33463 DECLARE_SET(Month);
Marko Mikulicic 0:c0ecb8bf28eb 33464 DECLARE_SET(Hours);
Marko Mikulicic 0:c0ecb8bf28eb 33465 DECLARE_SET(Minutes);
Marko Mikulicic 0:c0ecb8bf28eb 33466 DECLARE_SET(Seconds);
Marko Mikulicic 0:c0ecb8bf28eb 33467 DECLARE_SET(Milliseconds);
Marko Mikulicic 0:c0ecb8bf28eb 33468 d_set_cfunc_prop(v7, v7->vals.date_prototype, "setTime", Date_setTime);
Marko Mikulicic 0:c0ecb8bf28eb 33469 d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTimezoneOffset",
Marko Mikulicic 0:c0ecb8bf28eb 33470 Date_getTimezoneOffset);
Marko Mikulicic 0:c0ecb8bf28eb 33471 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33472
Marko Mikulicic 0:c0ecb8bf28eb 33473 #if V7_ENABLE__Date__now
Marko Mikulicic 0:c0ecb8bf28eb 33474 d_set_cfunc_prop(v7, date, "now", Date_now);
Marko Mikulicic 0:c0ecb8bf28eb 33475 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33476 #if V7_ENABLE__Date__parse
Marko Mikulicic 0:c0ecb8bf28eb 33477 d_set_cfunc_prop(v7, date, "parse", Date_parse);
Marko Mikulicic 0:c0ecb8bf28eb 33478 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33479 #if V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 33480 d_set_cfunc_prop(v7, date, "UTC", Date_UTC);
Marko Mikulicic 0:c0ecb8bf28eb 33481 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33482
Marko Mikulicic 0:c0ecb8bf28eb 33483 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 33484 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toString", Date_toString);
Marko Mikulicic 0:c0ecb8bf28eb 33485 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toISOString",
Marko Mikulicic 0:c0ecb8bf28eb 33486 Date_toISOString);
Marko Mikulicic 0:c0ecb8bf28eb 33487 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toUTCString",
Marko Mikulicic 0:c0ecb8bf28eb 33488 Date_toUTCString);
Marko Mikulicic 0:c0ecb8bf28eb 33489 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toDateString",
Marko Mikulicic 0:c0ecb8bf28eb 33490 Date_toDateString);
Marko Mikulicic 0:c0ecb8bf28eb 33491 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toTimeString",
Marko Mikulicic 0:c0ecb8bf28eb 33492 Date_toTimeString);
Marko Mikulicic 0:c0ecb8bf28eb 33493 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33494 #if V7_ENABLE__Date__toLocaleString
Marko Mikulicic 0:c0ecb8bf28eb 33495 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleString",
Marko Mikulicic 0:c0ecb8bf28eb 33496 Date_toLocaleString);
Marko Mikulicic 0:c0ecb8bf28eb 33497 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleDateString",
Marko Mikulicic 0:c0ecb8bf28eb 33498 Date_toLocaleDateString);
Marko Mikulicic 0:c0ecb8bf28eb 33499 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleTimeString",
Marko Mikulicic 0:c0ecb8bf28eb 33500 Date_toLocaleTimeString);
Marko Mikulicic 0:c0ecb8bf28eb 33501 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33502 #if V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 33503 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toJSON", Date_toJSON);
Marko Mikulicic 0:c0ecb8bf28eb 33504 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33505
Marko Mikulicic 0:c0ecb8bf28eb 33506 /*
Marko Mikulicic 0:c0ecb8bf28eb 33507 * GTM offset without DST
Marko Mikulicic 0:c0ecb8bf28eb 33508 * TODO(alashkin): check this
Marko Mikulicic 0:c0ecb8bf28eb 33509 * Could be changed to tm::tm_gmtoff,
Marko Mikulicic 0:c0ecb8bf28eb 33510 * but tm_gmtoff includes DST, so
Marko Mikulicic 0:c0ecb8bf28eb 33511 * side effects are possible
Marko Mikulicic 0:c0ecb8bf28eb 33512 */
Marko Mikulicic 0:c0ecb8bf28eb 33513 tzset();
Marko Mikulicic 0:c0ecb8bf28eb 33514 g_gmtoffms = timezone * msPerSecond;
Marko Mikulicic 0:c0ecb8bf28eb 33515 /*
Marko Mikulicic 0:c0ecb8bf28eb 33516 * tzname could be changed by localtime_r call,
Marko Mikulicic 0:c0ecb8bf28eb 33517 * so we have to store pointer
Marko Mikulicic 0:c0ecb8bf28eb 33518 * TODO(alashkin): need restart on tz change???
Marko Mikulicic 0:c0ecb8bf28eb 33519 */
Marko Mikulicic 0:c0ecb8bf28eb 33520 g_tzname = tzname[0];
Marko Mikulicic 0:c0ecb8bf28eb 33521 }
Marko Mikulicic 0:c0ecb8bf28eb 33522
Marko Mikulicic 0:c0ecb8bf28eb 33523 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 33524 }
Marko Mikulicic 0:c0ecb8bf28eb 33525 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 33526
Marko Mikulicic 0:c0ecb8bf28eb 33527 #endif /* V7_ENABLE__Date */
Marko Mikulicic 0:c0ecb8bf28eb 33528 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 33529 #line 1 "v7/src/std_function.c"
Marko Mikulicic 0:c0ecb8bf28eb 33530 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33531 /*
Marko Mikulicic 0:c0ecb8bf28eb 33532 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 33533 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 33534 */
Marko Mikulicic 0:c0ecb8bf28eb 33535
Marko Mikulicic 0:c0ecb8bf28eb 33536 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33537 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33538 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33539 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33540 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33541 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33542 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33543 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33544 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33545 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33546
Marko Mikulicic 0:c0ecb8bf28eb 33547 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 33548 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 33549 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 33550
Marko Mikulicic 0:c0ecb8bf28eb 33551 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33552 V7_PRIVATE enum v7_err Function_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33553 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33554 long i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33555 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 33556 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 33557 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 33558
Marko Mikulicic 0:c0ecb8bf28eb 33559 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33560
Marko Mikulicic 0:c0ecb8bf28eb 33561 if (num_args <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33562 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33563 }
Marko Mikulicic 0:c0ecb8bf28eb 33564
Marko Mikulicic 0:c0ecb8bf28eb 33565 mbuf_append(&m, "(function(", 10);
Marko Mikulicic 0:c0ecb8bf28eb 33566
Marko Mikulicic 0:c0ecb8bf28eb 33567 for (i = 0; i < num_args - 1; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 33568 rcode = obj_value_of(v7, v7_arg(v7, i), res);
Marko Mikulicic 0:c0ecb8bf28eb 33569 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33570 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33571 }
Marko Mikulicic 0:c0ecb8bf28eb 33572 if (v7_is_string(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 33573 if (i > 0) mbuf_append(&m, ",", 1);
Marko Mikulicic 0:c0ecb8bf28eb 33574 s = v7_get_string(v7, res, &size);
Marko Mikulicic 0:c0ecb8bf28eb 33575 mbuf_append(&m, s, size);
Marko Mikulicic 0:c0ecb8bf28eb 33576 }
Marko Mikulicic 0:c0ecb8bf28eb 33577 }
Marko Mikulicic 0:c0ecb8bf28eb 33578 mbuf_append(&m, "){", 2);
Marko Mikulicic 0:c0ecb8bf28eb 33579 rcode = obj_value_of(v7, v7_arg(v7, num_args - 1), res);
Marko Mikulicic 0:c0ecb8bf28eb 33580 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33581 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33582 }
Marko Mikulicic 0:c0ecb8bf28eb 33583 if (v7_is_string(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 33584 s = v7_get_string(v7, res, &size);
Marko Mikulicic 0:c0ecb8bf28eb 33585 mbuf_append(&m, s, size);
Marko Mikulicic 0:c0ecb8bf28eb 33586 }
Marko Mikulicic 0:c0ecb8bf28eb 33587 mbuf_append(&m, "})\0", 3);
Marko Mikulicic 0:c0ecb8bf28eb 33588
Marko Mikulicic 0:c0ecb8bf28eb 33589 rcode = v7_exec(v7, m.buf, res);
Marko Mikulicic 0:c0ecb8bf28eb 33590 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33591 rcode = v7_throwf(v7, SYNTAX_ERROR, "Invalid function body");
Marko Mikulicic 0:c0ecb8bf28eb 33592 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33593 }
Marko Mikulicic 0:c0ecb8bf28eb 33594
Marko Mikulicic 0:c0ecb8bf28eb 33595 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33596 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 33597 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33598 }
Marko Mikulicic 0:c0ecb8bf28eb 33599
Marko Mikulicic 0:c0ecb8bf28eb 33600 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33601 V7_PRIVATE enum v7_err Function_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33602 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33603 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33604 struct v7_js_function *func;
Marko Mikulicic 0:c0ecb8bf28eb 33605
Marko Mikulicic 0:c0ecb8bf28eb 33606 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33607 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33608 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33609 }
Marko Mikulicic 0:c0ecb8bf28eb 33610 if (!is_js_function(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33611 *res = v7_mk_number(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33612 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33613 }
Marko Mikulicic 0:c0ecb8bf28eb 33614
Marko Mikulicic 0:c0ecb8bf28eb 33615 func = get_js_function_struct(this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33616
Marko Mikulicic 0:c0ecb8bf28eb 33617 *res = v7_mk_number(v7, func->bcode->args_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 33618
Marko Mikulicic 0:c0ecb8bf28eb 33619 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33620 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33621 }
Marko Mikulicic 0:c0ecb8bf28eb 33622
Marko Mikulicic 0:c0ecb8bf28eb 33623 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33624 V7_PRIVATE enum v7_err Function_name(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33625 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33626 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33627 struct v7_js_function *func;
Marko Mikulicic 0:c0ecb8bf28eb 33628
Marko Mikulicic 0:c0ecb8bf28eb 33629 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33630 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33631 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33632 }
Marko Mikulicic 0:c0ecb8bf28eb 33633 if (!is_js_function(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33634 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33635 }
Marko Mikulicic 0:c0ecb8bf28eb 33636
Marko Mikulicic 0:c0ecb8bf28eb 33637 func = get_js_function_struct(this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33638
Marko Mikulicic 0:c0ecb8bf28eb 33639 assert(func->bcode != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33640
Marko Mikulicic 0:c0ecb8bf28eb 33641 assert(func->bcode->names_cnt >= 1);
Marko Mikulicic 0:c0ecb8bf28eb 33642 bcode_next_name_v(v7, func->bcode, func->bcode->ops.p, res);
Marko Mikulicic 0:c0ecb8bf28eb 33643
Marko Mikulicic 0:c0ecb8bf28eb 33644 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33645 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33646 }
Marko Mikulicic 0:c0ecb8bf28eb 33647
Marko Mikulicic 0:c0ecb8bf28eb 33648 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33649 V7_PRIVATE enum v7_err Function_apply(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33650 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33651 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33652 val_t this_arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33653 val_t func_args = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33654
Marko Mikulicic 0:c0ecb8bf28eb 33655 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33656 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33657 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33658 }
Marko Mikulicic 0:c0ecb8bf28eb 33659
Marko Mikulicic 0:c0ecb8bf28eb 33660 if (is_js_function(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33661 /*
Marko Mikulicic 0:c0ecb8bf28eb 33662 * `Function_apply` is a cfunction, so, GC is inhibited before calling it.
Marko Mikulicic 0:c0ecb8bf28eb 33663 * But the given function to call is a JS function, so we should enable GC;
Marko Mikulicic 0:c0ecb8bf28eb 33664 * otherwise, it will be inhibited during the whole execution of the given
Marko Mikulicic 0:c0ecb8bf28eb 33665 * JS function
Marko Mikulicic 0:c0ecb8bf28eb 33666 */
Marko Mikulicic 0:c0ecb8bf28eb 33667 v7_set_gc_enabled(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33668 }
Marko Mikulicic 0:c0ecb8bf28eb 33669
Marko Mikulicic 0:c0ecb8bf28eb 33670 rcode = b_apply(v7, this_obj, this_arg, func_args, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 33671 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33672 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33673 }
Marko Mikulicic 0:c0ecb8bf28eb 33674
Marko Mikulicic 0:c0ecb8bf28eb 33675 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33676 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33677 }
Marko Mikulicic 0:c0ecb8bf28eb 33678
Marko Mikulicic 0:c0ecb8bf28eb 33679 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33680 V7_PRIVATE enum v7_err Function_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33681 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33682 char *ops;
Marko Mikulicic 0:c0ecb8bf28eb 33683 char *name;
Marko Mikulicic 0:c0ecb8bf28eb 33684 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 33685 char buf[50];
Marko Mikulicic 0:c0ecb8bf28eb 33686 char *b = buf;
Marko Mikulicic 0:c0ecb8bf28eb 33687 struct v7_js_function *func = get_js_function_struct(v7_get_this(v7));
Marko Mikulicic 0:c0ecb8bf28eb 33688 int i;
Marko Mikulicic 0:c0ecb8bf28eb 33689
Marko Mikulicic 0:c0ecb8bf28eb 33690 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "[function");
Marko Mikulicic 0:c0ecb8bf28eb 33691
Marko Mikulicic 0:c0ecb8bf28eb 33692 assert(func->bcode != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33693 ops = func->bcode->ops.p;
Marko Mikulicic 0:c0ecb8bf28eb 33694
Marko Mikulicic 0:c0ecb8bf28eb 33695 /* first entry in name list */
Marko Mikulicic 0:c0ecb8bf28eb 33696 ops = bcode_next_name(ops, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 33697
Marko Mikulicic 0:c0ecb8bf28eb 33698 if (name_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33699 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), " %.*s", (int) name_len,
Marko Mikulicic 0:c0ecb8bf28eb 33700 name);
Marko Mikulicic 0:c0ecb8bf28eb 33701 }
Marko Mikulicic 0:c0ecb8bf28eb 33702 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "(");
Marko Mikulicic 0:c0ecb8bf28eb 33703 for (i = 0; i < func->bcode->args_cnt; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 33704 ops = bcode_next_name(ops, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 33705
Marko Mikulicic 0:c0ecb8bf28eb 33706 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s", (int) name_len,
Marko Mikulicic 0:c0ecb8bf28eb 33707 name);
Marko Mikulicic 0:c0ecb8bf28eb 33708 if (i < func->bcode->args_cnt - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33709 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 33710 }
Marko Mikulicic 0:c0ecb8bf28eb 33711 }
Marko Mikulicic 0:c0ecb8bf28eb 33712 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ")");
Marko Mikulicic 0:c0ecb8bf28eb 33713
Marko Mikulicic 0:c0ecb8bf28eb 33714 {
Marko Mikulicic 0:c0ecb8bf28eb 33715 uint8_t loc_cnt =
Marko Mikulicic 0:c0ecb8bf28eb 33716 func->bcode->names_cnt - func->bcode->args_cnt - 1 /*func name*/;
Marko Mikulicic 0:c0ecb8bf28eb 33717
Marko Mikulicic 0:c0ecb8bf28eb 33718 if (loc_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33719 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "{var ");
Marko Mikulicic 0:c0ecb8bf28eb 33720 for (i = 0; i < loc_cnt; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 33721 ops = bcode_next_name(ops, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 33722
Marko Mikulicic 0:c0ecb8bf28eb 33723 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s",
Marko Mikulicic 0:c0ecb8bf28eb 33724 (int) name_len, name);
Marko Mikulicic 0:c0ecb8bf28eb 33725 if (i < (loc_cnt - 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 33726 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 33727 }
Marko Mikulicic 0:c0ecb8bf28eb 33728 }
Marko Mikulicic 0:c0ecb8bf28eb 33729
Marko Mikulicic 0:c0ecb8bf28eb 33730 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "}");
Marko Mikulicic 0:c0ecb8bf28eb 33731 }
Marko Mikulicic 0:c0ecb8bf28eb 33732 }
Marko Mikulicic 0:c0ecb8bf28eb 33733
Marko Mikulicic 0:c0ecb8bf28eb 33734 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "]");
Marko Mikulicic 0:c0ecb8bf28eb 33735
Marko Mikulicic 0:c0ecb8bf28eb 33736 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 33737
Marko Mikulicic 0:c0ecb8bf28eb 33738 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33739 }
Marko Mikulicic 0:c0ecb8bf28eb 33740
Marko Mikulicic 0:c0ecb8bf28eb 33741 V7_PRIVATE void init_function(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 33742 val_t ctor = mk_cfunction_obj(v7, Function_ctor, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33743
Marko Mikulicic 0:c0ecb8bf28eb 33744 v7_set(v7, ctor, "prototype", 9, v7->vals.function_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 33745 v7_set(v7, v7->vals.global_object, "Function", 8, ctor);
Marko Mikulicic 0:c0ecb8bf28eb 33746 set_method(v7, v7->vals.function_prototype, "apply", Function_apply, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33747 set_method(v7, v7->vals.function_prototype, "toString", Function_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33748 v7_def(v7, v7->vals.function_prototype, "length", 6,
Marko Mikulicic 0:c0ecb8bf28eb 33749 (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)),
Marko Mikulicic 0:c0ecb8bf28eb 33750 v7_mk_cfunction(Function_length));
Marko Mikulicic 0:c0ecb8bf28eb 33751 v7_def(v7, v7->vals.function_prototype, "name", 4,
Marko Mikulicic 0:c0ecb8bf28eb 33752 (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)),
Marko Mikulicic 0:c0ecb8bf28eb 33753 v7_mk_cfunction(Function_name));
Marko Mikulicic 0:c0ecb8bf28eb 33754 }
Marko Mikulicic 0:c0ecb8bf28eb 33755
Marko Mikulicic 0:c0ecb8bf28eb 33756 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 33757 }
Marko Mikulicic 0:c0ecb8bf28eb 33758 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 33759 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 33760 #line 1 "v7/src/std_regex.c"
Marko Mikulicic 0:c0ecb8bf28eb 33761 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33762 /*
Marko Mikulicic 0:c0ecb8bf28eb 33763 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 33764 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 33765 */
Marko Mikulicic 0:c0ecb8bf28eb 33766
Marko Mikulicic 0:c0ecb8bf28eb 33767 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33768 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33769 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33770 /* Amalgamated: #include "v7/src/std_regex.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33771 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33772 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33773 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33774 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33775 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33776 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33777 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33778 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33779 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33780 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33781 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33782
Marko Mikulicic 0:c0ecb8bf28eb 33783 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 33784
Marko Mikulicic 0:c0ecb8bf28eb 33785 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33786 V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33787 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33788 long argnum = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33789
Marko Mikulicic 0:c0ecb8bf28eb 33790 if (argnum > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33791 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33792 val_t ro, fl;
Marko Mikulicic 0:c0ecb8bf28eb 33793 size_t re_len, flags_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33794 const char *re, *flags = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33795
Marko Mikulicic 0:c0ecb8bf28eb 33796 if (v7_is_regexp(v7, arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 33797 if (argnum > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33798 /* ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js */
Marko Mikulicic 0:c0ecb8bf28eb 33799 rcode = v7_throwf(v7, TYPE_ERROR, "invalid flags");
Marko Mikulicic 0:c0ecb8bf28eb 33800 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33801 }
Marko Mikulicic 0:c0ecb8bf28eb 33802 *res = arg;
Marko Mikulicic 0:c0ecb8bf28eb 33803 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33804 }
Marko Mikulicic 0:c0ecb8bf28eb 33805 rcode = to_string(v7, arg, &ro, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33806 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33807 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33808 }
Marko Mikulicic 0:c0ecb8bf28eb 33809
Marko Mikulicic 0:c0ecb8bf28eb 33810 if (argnum > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33811 rcode = to_string(v7, v7_arg(v7, 1), &fl, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33812 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33813 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33814 }
Marko Mikulicic 0:c0ecb8bf28eb 33815
Marko Mikulicic 0:c0ecb8bf28eb 33816 flags = v7_get_string(v7, &fl, &flags_len);
Marko Mikulicic 0:c0ecb8bf28eb 33817 }
Marko Mikulicic 0:c0ecb8bf28eb 33818 re = v7_get_string(v7, &ro, &re_len);
Marko Mikulicic 0:c0ecb8bf28eb 33819 rcode = v7_mk_regexp(v7, re, re_len, flags, flags_len, res);
Marko Mikulicic 0:c0ecb8bf28eb 33820 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33821 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33822 }
Marko Mikulicic 0:c0ecb8bf28eb 33823
Marko Mikulicic 0:c0ecb8bf28eb 33824 } else {
Marko Mikulicic 0:c0ecb8bf28eb 33825 rcode = v7_mk_regexp(v7, "(?:)", 4, NULL, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 33826 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33827 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33828 }
Marko Mikulicic 0:c0ecb8bf28eb 33829 }
Marko Mikulicic 0:c0ecb8bf28eb 33830
Marko Mikulicic 0:c0ecb8bf28eb 33831 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33832 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33833 }
Marko Mikulicic 0:c0ecb8bf28eb 33834
Marko Mikulicic 0:c0ecb8bf28eb 33835 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33836 V7_PRIVATE enum v7_err Regex_global(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33837 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33838 int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33839 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33840 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33841 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33842 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33843 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33844 }
Marko Mikulicic 0:c0ecb8bf28eb 33845
Marko Mikulicic 0:c0ecb8bf28eb 33846 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33847 flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 33848 }
Marko Mikulicic 0:c0ecb8bf28eb 33849
Marko Mikulicic 0:c0ecb8bf28eb 33850 *res = v7_mk_boolean(v7, flags & SLRE_FLAG_G);
Marko Mikulicic 0:c0ecb8bf28eb 33851
Marko Mikulicic 0:c0ecb8bf28eb 33852 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33853 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33854 }
Marko Mikulicic 0:c0ecb8bf28eb 33855
Marko Mikulicic 0:c0ecb8bf28eb 33856 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33857 V7_PRIVATE enum v7_err Regex_ignoreCase(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33858 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33859 int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33860 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33861 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33862 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33863 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33864 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33865 }
Marko Mikulicic 0:c0ecb8bf28eb 33866
Marko Mikulicic 0:c0ecb8bf28eb 33867 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33868 flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 33869 }
Marko Mikulicic 0:c0ecb8bf28eb 33870
Marko Mikulicic 0:c0ecb8bf28eb 33871 *res = v7_mk_boolean(v7, flags & SLRE_FLAG_I);
Marko Mikulicic 0:c0ecb8bf28eb 33872
Marko Mikulicic 0:c0ecb8bf28eb 33873 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33874 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33875 }
Marko Mikulicic 0:c0ecb8bf28eb 33876
Marko Mikulicic 0:c0ecb8bf28eb 33877 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33878 V7_PRIVATE enum v7_err Regex_multiline(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33879 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33880 int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33881 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33882 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33883 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33884 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33885 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33886 }
Marko Mikulicic 0:c0ecb8bf28eb 33887
Marko Mikulicic 0:c0ecb8bf28eb 33888 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33889 flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 33890 }
Marko Mikulicic 0:c0ecb8bf28eb 33891
Marko Mikulicic 0:c0ecb8bf28eb 33892 *res = v7_mk_boolean(v7, flags & SLRE_FLAG_M);
Marko Mikulicic 0:c0ecb8bf28eb 33893
Marko Mikulicic 0:c0ecb8bf28eb 33894 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33895 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33896 }
Marko Mikulicic 0:c0ecb8bf28eb 33897
Marko Mikulicic 0:c0ecb8bf28eb 33898 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33899 V7_PRIVATE enum v7_err Regex_source(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33900 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33901 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33902 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33903 const char *buf = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33904 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33905
Marko Mikulicic 0:c0ecb8bf28eb 33906 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33907 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33908 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33909 }
Marko Mikulicic 0:c0ecb8bf28eb 33910
Marko Mikulicic 0:c0ecb8bf28eb 33911 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33912 buf = v7_get_string(v7, &v7_get_regexp_struct(v7, r)->regexp_string, &len);
Marko Mikulicic 0:c0ecb8bf28eb 33913 }
Marko Mikulicic 0:c0ecb8bf28eb 33914
Marko Mikulicic 0:c0ecb8bf28eb 33915 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33916
Marko Mikulicic 0:c0ecb8bf28eb 33917 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33918 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33919 }
Marko Mikulicic 0:c0ecb8bf28eb 33920
Marko Mikulicic 0:c0ecb8bf28eb 33921 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33922 V7_PRIVATE enum v7_err Regex_get_lastIndex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33923 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33924 long lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33925 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33926
Marko Mikulicic 0:c0ecb8bf28eb 33927 if (v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33928 lastIndex = v7_get_regexp_struct(v7, this_obj)->lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 33929 }
Marko Mikulicic 0:c0ecb8bf28eb 33930
Marko Mikulicic 0:c0ecb8bf28eb 33931 *res = v7_mk_number(v7, lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33932
Marko Mikulicic 0:c0ecb8bf28eb 33933 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33934 }
Marko Mikulicic 0:c0ecb8bf28eb 33935
Marko Mikulicic 0:c0ecb8bf28eb 33936 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33937 V7_PRIVATE enum v7_err Regex_set_lastIndex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33938 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33939 long lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33940 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33941
Marko Mikulicic 0:c0ecb8bf28eb 33942 if (v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33943 rcode = to_long(v7, v7_arg(v7, 0), 0, &lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33944 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33945 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33946 }
Marko Mikulicic 0:c0ecb8bf28eb 33947 v7_get_regexp_struct(v7, this_obj)->lastIndex = lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 33948 }
Marko Mikulicic 0:c0ecb8bf28eb 33949
Marko Mikulicic 0:c0ecb8bf28eb 33950 *res = v7_mk_number(v7, lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33951
Marko Mikulicic 0:c0ecb8bf28eb 33952 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33953 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33954 }
Marko Mikulicic 0:c0ecb8bf28eb 33955
Marko Mikulicic 0:c0ecb8bf28eb 33956 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33957 V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, val_t rx, val_t vstr, int lind,
Marko Mikulicic 0:c0ecb8bf28eb 33958 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33959 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33960 if (v7_is_regexp(v7, rx)) {
Marko Mikulicic 0:c0ecb8bf28eb 33961 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33962 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 33963 struct slre_loot sub;
Marko Mikulicic 0:c0ecb8bf28eb 33964 struct slre_cap *ptok = sub.caps;
Marko Mikulicic 0:c0ecb8bf28eb 33965 const char *str = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33966 const char *end = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33967 const char *begin = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33968 struct v7_regexp *rp = v7_get_regexp_struct(v7, rx);
Marko Mikulicic 0:c0ecb8bf28eb 33969 int flag_g = slre_get_flags(rp->compiled_regexp) & SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 33970
Marko Mikulicic 0:c0ecb8bf28eb 33971 rcode = to_string(v7, vstr, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33972 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33973 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33974 }
Marko Mikulicic 0:c0ecb8bf28eb 33975 str = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 33976 end = str + len;
Marko Mikulicic 0:c0ecb8bf28eb 33977 begin = str;
Marko Mikulicic 0:c0ecb8bf28eb 33978
Marko Mikulicic 0:c0ecb8bf28eb 33979 if (rp->lastIndex < 0) rp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33980 if (flag_g || lind) begin = utfnshift(str, rp->lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33981
Marko Mikulicic 0:c0ecb8bf28eb 33982 if (!slre_exec(rp->compiled_regexp, 0, begin, end, &sub)) {
Marko Mikulicic 0:c0ecb8bf28eb 33983 int i;
Marko Mikulicic 0:c0ecb8bf28eb 33984 val_t arr = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33985 char *old_mbuf_base = v7->owned_strings.buf;
Marko Mikulicic 0:c0ecb8bf28eb 33986 ptrdiff_t rel = 0; /* creating strings might relocate the mbuf */
Marko Mikulicic 0:c0ecb8bf28eb 33987
Marko Mikulicic 0:c0ecb8bf28eb 33988 for (i = 0; i < sub.num_captures; i++, ptok++) {
Marko Mikulicic 0:c0ecb8bf28eb 33989 rel = v7->owned_strings.buf - old_mbuf_base;
Marko Mikulicic 0:c0ecb8bf28eb 33990 v7_array_push(v7, arr, v7_mk_string(v7, ptok->start + rel,
Marko Mikulicic 0:c0ecb8bf28eb 33991 ptok->end - ptok->start, 1));
Marko Mikulicic 0:c0ecb8bf28eb 33992 }
Marko Mikulicic 0:c0ecb8bf28eb 33993 if (flag_g) rp->lastIndex = utfnlen(str, sub.caps->end + rel - str);
Marko Mikulicic 0:c0ecb8bf28eb 33994 v7_def(v7, arr, "index", 5, V7_DESC_WRITABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 33995 v7_mk_number(v7, utfnlen(str + rel, sub.caps->start - str)));
Marko Mikulicic 0:c0ecb8bf28eb 33996 *res = arr;
Marko Mikulicic 0:c0ecb8bf28eb 33997 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33998 } else {
Marko Mikulicic 0:c0ecb8bf28eb 33999 rp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34000 }
Marko Mikulicic 0:c0ecb8bf28eb 34001 }
Marko Mikulicic 0:c0ecb8bf28eb 34002
Marko Mikulicic 0:c0ecb8bf28eb 34003 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 34004
Marko Mikulicic 0:c0ecb8bf28eb 34005 clean:
Marko Mikulicic 0:c0ecb8bf28eb 34006 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34007 }
Marko Mikulicic 0:c0ecb8bf28eb 34008
Marko Mikulicic 0:c0ecb8bf28eb 34009 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 34010 V7_PRIVATE enum v7_err Regex_exec(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 34011 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 34012 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34013
Marko Mikulicic 0:c0ecb8bf28eb 34014 if (v7_argc(v7) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34015 rcode = rx_exec(v7, this_obj, v7_arg(v7, 0), 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 34016 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34017 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34018 }
Marko Mikulicic 0:c0ecb8bf28eb 34019 } else {
Marko Mikulicic 0:c0ecb8bf28eb 34020 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 34021 }
Marko Mikulicic 0:c0ecb8bf28eb 34022
Marko Mikulicic 0:c0ecb8bf28eb 34023 clean:
Marko Mikulicic 0:c0ecb8bf28eb 34024 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34025 }
Marko Mikulicic 0:c0ecb8bf28eb 34026
Marko Mikulicic 0:c0ecb8bf28eb 34027 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 34028 V7_PRIVATE enum v7_err Regex_test(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 34029 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 34030 val_t tmp = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 34031
Marko Mikulicic 0:c0ecb8bf28eb 34032 rcode = Regex_exec(v7, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 34033 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34034 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34035 }
Marko Mikulicic 0:c0ecb8bf28eb 34036
Marko Mikulicic 0:c0ecb8bf28eb 34037 *res = v7_mk_boolean(v7, !v7_is_null(tmp));
Marko Mikulicic 0:c0ecb8bf28eb 34038
Marko Mikulicic 0:c0ecb8bf28eb 34039 clean:
Marko Mikulicic 0:c0ecb8bf28eb 34040 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34041 }
Marko Mikulicic 0:c0ecb8bf28eb 34042
Marko Mikulicic 0:c0ecb8bf28eb 34043 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 34044 V7_PRIVATE enum v7_err Regex_flags(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 34045 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 34046 char buf[3] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 34047 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34048 struct v7_regexp *rp = v7_get_regexp_struct(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34049 size_t n = get_regexp_flags_str(v7, rp, buf);
Marko Mikulicic 0:c0ecb8bf28eb 34050 *res = v7_mk_string(v7, buf, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 34051
Marko Mikulicic 0:c0ecb8bf28eb 34052 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34053 }
Marko Mikulicic 0:c0ecb8bf28eb 34054
Marko Mikulicic 0:c0ecb8bf28eb 34055 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 34056 V7_PRIVATE enum v7_err Regex_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 34057 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 34058 size_t n1, n2 = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34059 char s2[3] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 34060 char buf[50];
Marko Mikulicic 0:c0ecb8bf28eb 34061 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34062 struct v7_regexp *rp;
Marko Mikulicic 0:c0ecb8bf28eb 34063 const char *s1;
Marko Mikulicic 0:c0ecb8bf28eb 34064
Marko Mikulicic 0:c0ecb8bf28eb 34065 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34066 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34067 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34068 }
Marko Mikulicic 0:c0ecb8bf28eb 34069
Marko Mikulicic 0:c0ecb8bf28eb 34070 if (!v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 34071 rcode = v7_throwf(v7, TYPE_ERROR, "Not a regexp");
Marko Mikulicic 0:c0ecb8bf28eb 34072 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34073 }
Marko Mikulicic 0:c0ecb8bf28eb 34074
Marko Mikulicic 0:c0ecb8bf28eb 34075 rp = v7_get_regexp_struct(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34076 s1 = v7_get_string(v7, &rp->regexp_string, &n1);
Marko Mikulicic 0:c0ecb8bf28eb 34077 n2 = get_regexp_flags_str(v7, rp, s2);
Marko Mikulicic 0:c0ecb8bf28eb 34078
Marko Mikulicic 0:c0ecb8bf28eb 34079 c_snprintf(buf, sizeof(buf), "/%.*s/%.*s", (int) n1, s1, (int) n2, s2);
Marko Mikulicic 0:c0ecb8bf28eb 34080
Marko Mikulicic 0:c0ecb8bf28eb 34081 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 34082
Marko Mikulicic 0:c0ecb8bf28eb 34083 clean:
Marko Mikulicic 0:c0ecb8bf28eb 34084 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34085 }
Marko Mikulicic 0:c0ecb8bf28eb 34086
Marko Mikulicic 0:c0ecb8bf28eb 34087 V7_PRIVATE void init_regex(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 34088 val_t ctor =
Marko Mikulicic 0:c0ecb8bf28eb 34089 mk_cfunction_obj_with_proto(v7, Regex_ctor, 1, v7->vals.regexp_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 34090 val_t lastIndex = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34091
Marko Mikulicic 0:c0ecb8bf28eb 34092 v7_def(v7, v7->vals.global_object, "RegExp", 6, V7_DESC_ENUMERABLE(0), ctor);
Marko Mikulicic 0:c0ecb8bf28eb 34093
Marko Mikulicic 0:c0ecb8bf28eb 34094 set_cfunc_prop(v7, v7->vals.regexp_prototype, "exec", Regex_exec);
Marko Mikulicic 0:c0ecb8bf28eb 34095 set_cfunc_prop(v7, v7->vals.regexp_prototype, "test", Regex_test);
Marko Mikulicic 0:c0ecb8bf28eb 34096 set_method(v7, v7->vals.regexp_prototype, "toString", Regex_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 34097
Marko Mikulicic 0:c0ecb8bf28eb 34098 v7_def(v7, v7->vals.regexp_prototype, "global", 6, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34099 v7_mk_cfunction(Regex_global));
Marko Mikulicic 0:c0ecb8bf28eb 34100 v7_def(v7, v7->vals.regexp_prototype, "ignoreCase", 10, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34101 v7_mk_cfunction(Regex_ignoreCase));
Marko Mikulicic 0:c0ecb8bf28eb 34102 v7_def(v7, v7->vals.regexp_prototype, "multiline", 9, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34103 v7_mk_cfunction(Regex_multiline));
Marko Mikulicic 0:c0ecb8bf28eb 34104 v7_def(v7, v7->vals.regexp_prototype, "source", 6, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34105 v7_mk_cfunction(Regex_source));
Marko Mikulicic 0:c0ecb8bf28eb 34106 v7_def(v7, v7->vals.regexp_prototype, "flags", 5, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34107 v7_mk_cfunction(Regex_flags));
Marko Mikulicic 0:c0ecb8bf28eb 34108
Marko Mikulicic 0:c0ecb8bf28eb 34109 v7_array_set(v7, lastIndex, 0, v7_mk_cfunction(Regex_get_lastIndex));
Marko Mikulicic 0:c0ecb8bf28eb 34110 v7_array_set(v7, lastIndex, 1, v7_mk_cfunction(Regex_set_lastIndex));
Marko Mikulicic 0:c0ecb8bf28eb 34111 v7_def(v7, v7->vals.regexp_prototype, "lastIndex", 9,
Marko Mikulicic 0:c0ecb8bf28eb 34112 (V7_DESC_GETTER(1) | V7_DESC_SETTER(1)), lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 34113 }
Marko Mikulicic 0:c0ecb8bf28eb 34114
Marko Mikulicic 0:c0ecb8bf28eb 34115 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 34116 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 34117 #line 1 "v7/src/std_proxy.c"
Marko Mikulicic 0:c0ecb8bf28eb 34118 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34119 /*
Marko Mikulicic 0:c0ecb8bf28eb 34120 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 34121 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 34122 */
Marko Mikulicic 0:c0ecb8bf28eb 34123
Marko Mikulicic 0:c0ecb8bf28eb 34124 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34125 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34126 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34127 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34128 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34129 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34130 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34131 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34132 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34133 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34134
Marko Mikulicic 0:c0ecb8bf28eb 34135 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 34136 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 34137 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 34138
Marko Mikulicic 0:c0ecb8bf28eb 34139 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 34140
Marko Mikulicic 0:c0ecb8bf28eb 34141 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 34142 V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 34143 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 34144 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34145 val_t target_v = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 34146 val_t handler_v = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 34147 struct v7_object *t = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 34148 v7_prop_attr_desc_t attrs_desc =
Marko Mikulicic 0:c0ecb8bf28eb 34149 (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 34150
Marko Mikulicic 0:c0ecb8bf28eb 34151 if (this_obj == v7_get_global(v7) || !v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 34152 rcode = v7_throwf(v7, TYPE_ERROR, "Wrong 'this' object for Proxy ctor");
Marko Mikulicic 0:c0ecb8bf28eb 34153 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34154 }
Marko Mikulicic 0:c0ecb8bf28eb 34155
Marko Mikulicic 0:c0ecb8bf28eb 34156 if (!v7_is_object(target_v) || !v7_is_object(handler_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 34157 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 34158 v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 34159 "Cannot create proxy with a non-object as target or handler");
Marko Mikulicic 0:c0ecb8bf28eb 34160 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34161 }
Marko Mikulicic 0:c0ecb8bf28eb 34162
Marko Mikulicic 0:c0ecb8bf28eb 34163 t = get_object_struct(this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34164 t->attributes |= V7_OBJ_PROXY;
Marko Mikulicic 0:c0ecb8bf28eb 34165
Marko Mikulicic 0:c0ecb8bf28eb 34166 v7_def(v7, this_obj, _V7_PROXY_TARGET_NAME, ~0, attrs_desc, target_v);
Marko Mikulicic 0:c0ecb8bf28eb 34167 v7_def(v7, this_obj, _V7_PROXY_HANDLER_NAME, ~0, attrs_desc, handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 34168
Marko Mikulicic 0:c0ecb8bf28eb 34169 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 34170
Marko Mikulicic 0:c0ecb8bf28eb 34171 clean:
Marko Mikulicic 0:c0ecb8bf28eb 34172 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34173 }
Marko Mikulicic 0:c0ecb8bf28eb 34174
Marko Mikulicic 0:c0ecb8bf28eb 34175 V7_PRIVATE void init_proxy(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 34176 /*v7_prop_attr_desc_t attrs_desc =*/
Marko Mikulicic 0:c0ecb8bf28eb 34177 /*(V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));*/
Marko Mikulicic 0:c0ecb8bf28eb 34178 val_t proxy =
Marko Mikulicic 0:c0ecb8bf28eb 34179 mk_cfunction_obj_with_proto(v7, Proxy_ctor, 1, v7->vals.proxy_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 34180
Marko Mikulicic 0:c0ecb8bf28eb 34181 v7_def(v7, v7->vals.global_object, "Proxy", ~0, V7_DESC_ENUMERABLE(0), proxy);
Marko Mikulicic 0:c0ecb8bf28eb 34182 }
Marko Mikulicic 0:c0ecb8bf28eb 34183
Marko Mikulicic 0:c0ecb8bf28eb 34184 V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len) {
Marko Mikulicic 0:c0ecb8bf28eb 34185 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34186 if (name_len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 34187 name_len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 34188 }
Marko Mikulicic 0:c0ecb8bf28eb 34189 if (name_len == 5 && (memcmp(name, _V7_PROXY_TARGET_NAME, name_len) == 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 34190 memcmp(name, _V7_PROXY_HANDLER_NAME, name_len) == 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 34191 ret = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34192 }
Marko Mikulicic 0:c0ecb8bf28eb 34193 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 34194 }
Marko Mikulicic 0:c0ecb8bf28eb 34195
Marko Mikulicic 0:c0ecb8bf28eb 34196 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 34197
Marko Mikulicic 0:c0ecb8bf28eb 34198 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 34199 }
Marko Mikulicic 0:c0ecb8bf28eb 34200 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 34201 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 34202 #line 1 "v7/src/main.c"
Marko Mikulicic 0:c0ecb8bf28eb 34203 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34204 /*
Marko Mikulicic 0:c0ecb8bf28eb 34205 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 34206 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 34207 */
Marko Mikulicic 0:c0ecb8bf28eb 34208
Marko Mikulicic 0:c0ecb8bf28eb 34209 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34210 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34211 /* Amalgamated: #include "v7/src/freeze.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34212 /* Amalgamated: #include "v7/src/main.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34213 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34214 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34215 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34216 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34217 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34218 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34219
Marko Mikulicic 0:c0ecb8bf28eb 34220 #if defined(_MSC_VER) && _MSC_VER >= 1800
Marko Mikulicic 0:c0ecb8bf28eb 34221 #define fileno _fileno
Marko Mikulicic 0:c0ecb8bf28eb 34222 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34223
Marko Mikulicic 0:c0ecb8bf28eb 34224 #ifdef V7_EXE
Marko Mikulicic 0:c0ecb8bf28eb 34225 #define V7_MAIN
Marko Mikulicic 0:c0ecb8bf28eb 34226 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34227
Marko Mikulicic 0:c0ecb8bf28eb 34228 #ifdef V7_MAIN
Marko Mikulicic 0:c0ecb8bf28eb 34229
Marko Mikulicic 0:c0ecb8bf28eb 34230 #include <sys/stat.h>
Marko Mikulicic 0:c0ecb8bf28eb 34231
Marko Mikulicic 0:c0ecb8bf28eb 34232 static void show_usage(char *argv[]) {
Marko Mikulicic 0:c0ecb8bf28eb 34233 fprintf(stderr, "V7 version %s (c) Cesanta Software, built on %s\n",
Marko Mikulicic 0:c0ecb8bf28eb 34234 V7_VERSION, __DATE__);
Marko Mikulicic 0:c0ecb8bf28eb 34235 fprintf(stderr, "Usage: %s [OPTIONS] js_file ...\n", argv[0]);
Marko Mikulicic 0:c0ecb8bf28eb 34236 fprintf(stderr, "%s\n", "OPTIONS:");
Marko Mikulicic 0:c0ecb8bf28eb 34237 fprintf(stderr, "%s\n", " -e <expr> execute expression");
Marko Mikulicic 0:c0ecb8bf28eb 34238 fprintf(stderr, "%s\n", " -t dump generated text AST");
Marko Mikulicic 0:c0ecb8bf28eb 34239 fprintf(stderr, "%s\n", " -b dump generated binary AST");
Marko Mikulicic 0:c0ecb8bf28eb 34240 fprintf(stderr, "%s\n", " -c dump compiled binary bcode");
Marko Mikulicic 0:c0ecb8bf28eb 34241 fprintf(stderr, "%s\n", " -mm dump memory stats");
Marko Mikulicic 0:c0ecb8bf28eb 34242 fprintf(stderr, "%s\n", " -vo <n> object arena size");
Marko Mikulicic 0:c0ecb8bf28eb 34243 fprintf(stderr, "%s\n", " -vf <n> function arena size");
Marko Mikulicic 0:c0ecb8bf28eb 34244 fprintf(stderr, "%s\n", " -vp <n> property arena size");
Marko Mikulicic 0:c0ecb8bf28eb 34245 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34246 fprintf(stderr, "%s\n", " -freeze filename dump JS heap into a file");
Marko Mikulicic 0:c0ecb8bf28eb 34247 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34248 exit(EXIT_FAILURE);
Marko Mikulicic 0:c0ecb8bf28eb 34249 }
Marko Mikulicic 0:c0ecb8bf28eb 34250
Marko Mikulicic 0:c0ecb8bf28eb 34251 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 34252 static void dump_mm_arena_stats(const char *msg, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 34253 printf("%s: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT
Marko Mikulicic 0:c0ecb8bf28eb 34254 ", alive %lu\n",
Marko Mikulicic 0:c0ecb8bf28eb 34255 msg, a->allocations, a->garbage, gc_arena_size(a), a->alive);
Marko Mikulicic 0:c0ecb8bf28eb 34256 printf(
Marko Mikulicic 0:c0ecb8bf28eb 34257 "%s: (bytes: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT
Marko Mikulicic 0:c0ecb8bf28eb 34258 ", alive %lu)\n",
Marko Mikulicic 0:c0ecb8bf28eb 34259 msg, a->allocations * a->cell_size, a->garbage * a->cell_size,
Marko Mikulicic 0:c0ecb8bf28eb 34260 gc_arena_size(a) * a->cell_size, a->alive * a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 34261 }
Marko Mikulicic 0:c0ecb8bf28eb 34262
Marko Mikulicic 0:c0ecb8bf28eb 34263 static void dump_mm_stats(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 34264 dump_mm_arena_stats("object: ", &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 34265 dump_mm_arena_stats("function: ", &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 34266 dump_mm_arena_stats("property: ", &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 34267 printf("string arena len: %" SIZE_T_FMT "\n", v7->owned_strings.len);
Marko Mikulicic 0:c0ecb8bf28eb 34268 printf("Total heap size: %" SIZE_T_FMT "\n",
Marko Mikulicic 0:c0ecb8bf28eb 34269 v7->owned_strings.len +
Marko Mikulicic 0:c0ecb8bf28eb 34270 gc_arena_size(&v7->generic_object_arena) *
Marko Mikulicic 0:c0ecb8bf28eb 34271 v7->generic_object_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 34272 gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 34273 gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 34274 }
Marko Mikulicic 0:c0ecb8bf28eb 34275 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34276
Marko Mikulicic 0:c0ecb8bf28eb 34277 int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *),
Marko Mikulicic 0:c0ecb8bf28eb 34278 void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *)) {
Marko Mikulicic 0:c0ecb8bf28eb 34279 int exit_rcode = EXIT_SUCCESS;
Marko Mikulicic 0:c0ecb8bf28eb 34280 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 34281 struct v7_create_opts opts;
Marko Mikulicic 0:c0ecb8bf28eb 34282 int as_json = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34283 int i, j, show_ast = 0, binary_ast = 0, dump_bcode = 0, dump_stats = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34284 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 34285 int nexprs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34286 const char *exprs[16];
Marko Mikulicic 0:c0ecb8bf28eb 34287
Marko Mikulicic 0:c0ecb8bf28eb 34288 memset(&opts, 0, sizeof(opts));
Marko Mikulicic 0:c0ecb8bf28eb 34289
Marko Mikulicic 0:c0ecb8bf28eb 34290 (void) show_ast;
Marko Mikulicic 0:c0ecb8bf28eb 34291 (void) binary_ast;
Marko Mikulicic 0:c0ecb8bf28eb 34292 (void) dump_bcode;
Marko Mikulicic 0:c0ecb8bf28eb 34293
Marko Mikulicic 0:c0ecb8bf28eb 34294 /* Execute inline code */
Marko Mikulicic 0:c0ecb8bf28eb 34295 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 34296 if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34297 exprs[nexprs++] = argv[i + 1];
Marko Mikulicic 0:c0ecb8bf28eb 34298 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34299 } else if (strcmp(argv[i], "-t") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34300 show_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34301 } else if (strcmp(argv[i], "-b") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34302 show_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34303 binary_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34304 } else if (strcmp(argv[i], "-c") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34305 binary_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34306 dump_bcode = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34307 } else if (strcmp(argv[i], "-h") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34308 show_usage(argv);
Marko Mikulicic 0:c0ecb8bf28eb 34309 } else if (strcmp(argv[i], "-j") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34310 as_json = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34311 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 34312 } else if (strcmp(argv[i], "-mm") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34313 dump_stats = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34314 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34315 } else if (strcmp(argv[i], "-vo") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34316 opts.object_arena_size = atoi(argv[i + 1]);
Marko Mikulicic 0:c0ecb8bf28eb 34317 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34318 } else if (strcmp(argv[i], "-vf") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34319 opts.function_arena_size = atoi(argv[i + 1]);
Marko Mikulicic 0:c0ecb8bf28eb 34320 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34321 } else if (strcmp(argv[i], "-vp") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34322 opts.property_arena_size = atoi(argv[i + 1]);
Marko Mikulicic 0:c0ecb8bf28eb 34323 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34324 }
Marko Mikulicic 0:c0ecb8bf28eb 34325 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34326 else if (strcmp(argv[i], "-freeze") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34327 opts.freeze_file = argv[i + 1];
Marko Mikulicic 0:c0ecb8bf28eb 34328 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34329 }
Marko Mikulicic 0:c0ecb8bf28eb 34330 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34331 }
Marko Mikulicic 0:c0ecb8bf28eb 34332
Marko Mikulicic 0:c0ecb8bf28eb 34333 #ifndef V7_ALLOW_ARGLESS_MAIN
Marko Mikulicic 0:c0ecb8bf28eb 34334 if (argc == 1) {
Marko Mikulicic 0:c0ecb8bf28eb 34335 show_usage(argv);
Marko Mikulicic 0:c0ecb8bf28eb 34336 }
Marko Mikulicic 0:c0ecb8bf28eb 34337 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34338
Marko Mikulicic 0:c0ecb8bf28eb 34339 v7 = v7_create_opt(opts);
Marko Mikulicic 0:c0ecb8bf28eb 34340 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 34341
Marko Mikulicic 0:c0ecb8bf28eb 34342 if (pre_freeze_init != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34343 pre_freeze_init(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34344 }
Marko Mikulicic 0:c0ecb8bf28eb 34345
Marko Mikulicic 0:c0ecb8bf28eb 34346 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34347 /*
Marko Mikulicic 0:c0ecb8bf28eb 34348 * Skip pre_init if freezing, but still execute cmdline expressions.
Marko Mikulicic 0:c0ecb8bf28eb 34349 * This makes it easier to add custom code when freezing from cmdline.
Marko Mikulicic 0:c0ecb8bf28eb 34350 */
Marko Mikulicic 0:c0ecb8bf28eb 34351 if (opts.freeze_file == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34352 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34353
Marko Mikulicic 0:c0ecb8bf28eb 34354 if (pre_init != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34355 pre_init(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34356 }
Marko Mikulicic 0:c0ecb8bf28eb 34357
Marko Mikulicic 0:c0ecb8bf28eb 34358 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34359 }
Marko Mikulicic 0:c0ecb8bf28eb 34360 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34361
Marko Mikulicic 0:c0ecb8bf28eb 34362 #if V7_ENABLE__Memory__stats > 0 && !defined(V7_DISABLE_GC)
Marko Mikulicic 0:c0ecb8bf28eb 34363 if (dump_stats) {
Marko Mikulicic 0:c0ecb8bf28eb 34364 printf("Memory stats during init:\n");
Marko Mikulicic 0:c0ecb8bf28eb 34365 dump_mm_stats(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34366 v7_gc(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 34367 printf("Memory stats before run:\n");
Marko Mikulicic 0:c0ecb8bf28eb 34368 dump_mm_stats(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34369 }
Marko Mikulicic 0:c0ecb8bf28eb 34370 #else
Marko Mikulicic 0:c0ecb8bf28eb 34371 (void) dump_stats;
Marko Mikulicic 0:c0ecb8bf28eb 34372 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34373
Marko Mikulicic 0:c0ecb8bf28eb 34374 /* Execute inline expressions */
Marko Mikulicic 0:c0ecb8bf28eb 34375 for (j = 0; j < nexprs; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 34376 enum v7_err (*exec)(struct v7 *, const char *, v7_val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 34377 exec = v7_exec;
Marko Mikulicic 0:c0ecb8bf28eb 34378
Marko Mikulicic 0:c0ecb8bf28eb 34379 if (show_ast || dump_bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 34380 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 34381 if (v7_compile(exprs[j], binary_ast, dump_bcode, stdout) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34382 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34383 fprintf(stderr, "%s\n", "parse error");
Marko Mikulicic 0:c0ecb8bf28eb 34384 }
Marko Mikulicic 0:c0ecb8bf28eb 34385 #else /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34386 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34387 fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER");
Marko Mikulicic 0:c0ecb8bf28eb 34388 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34389 } else if (exec(v7, exprs[j], &res) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34390 v7_print_error(stderr, v7, exprs[j], res);
Marko Mikulicic 0:c0ecb8bf28eb 34391 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34392 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 34393 }
Marko Mikulicic 0:c0ecb8bf28eb 34394 }
Marko Mikulicic 0:c0ecb8bf28eb 34395
Marko Mikulicic 0:c0ecb8bf28eb 34396 /* Execute files */
Marko Mikulicic 0:c0ecb8bf28eb 34397 for (; i < argc; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 34398 if (show_ast || dump_bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 34399 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 34400 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 34401 char *source_code;
Marko Mikulicic 0:c0ecb8bf28eb 34402 if ((source_code = cs_read_file(argv[i], &size)) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34403 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34404 fprintf(stderr, "Cannot read [%s]\n", argv[i]);
Marko Mikulicic 0:c0ecb8bf28eb 34405 } else {
Marko Mikulicic 0:c0ecb8bf28eb 34406 if (_v7_compile(source_code, size, binary_ast, dump_bcode, stdout) !=
Marko Mikulicic 0:c0ecb8bf28eb 34407 V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34408 fprintf(stderr, "error: %s\n", v7->error_msg);
Marko Mikulicic 0:c0ecb8bf28eb 34409 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34410 exit(exit_rcode);
Marko Mikulicic 0:c0ecb8bf28eb 34411 }
Marko Mikulicic 0:c0ecb8bf28eb 34412 free(source_code);
Marko Mikulicic 0:c0ecb8bf28eb 34413 }
Marko Mikulicic 0:c0ecb8bf28eb 34414 #else /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34415 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34416 fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER");
Marko Mikulicic 0:c0ecb8bf28eb 34417 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34418 } else if (v7_exec_file(v7, argv[i], &res) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34419 v7_print_error(stderr, v7, argv[i], res);
Marko Mikulicic 0:c0ecb8bf28eb 34420 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 34421 }
Marko Mikulicic 0:c0ecb8bf28eb 34422 }
Marko Mikulicic 0:c0ecb8bf28eb 34423
Marko Mikulicic 0:c0ecb8bf28eb 34424 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34425 if (opts.freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34426 freeze(v7, opts.freeze_file);
Marko Mikulicic 0:c0ecb8bf28eb 34427 exit(0);
Marko Mikulicic 0:c0ecb8bf28eb 34428 }
Marko Mikulicic 0:c0ecb8bf28eb 34429 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34430
Marko Mikulicic 0:c0ecb8bf28eb 34431 if (!(show_ast || dump_bcode)) {
Marko Mikulicic 0:c0ecb8bf28eb 34432 char buf[2000];
Marko Mikulicic 0:c0ecb8bf28eb 34433 char *s = v7_stringify(v7, res, buf, sizeof(buf),
Marko Mikulicic 0:c0ecb8bf28eb 34434 as_json ? V7_STRINGIFY_JSON : V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 34435 printf("%s\n", s);
Marko Mikulicic 0:c0ecb8bf28eb 34436 if (s != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 34437 free(s);
Marko Mikulicic 0:c0ecb8bf28eb 34438 }
Marko Mikulicic 0:c0ecb8bf28eb 34439 }
Marko Mikulicic 0:c0ecb8bf28eb 34440
Marko Mikulicic 0:c0ecb8bf28eb 34441 if (post_init != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34442 post_init(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34443 }
Marko Mikulicic 0:c0ecb8bf28eb 34444
Marko Mikulicic 0:c0ecb8bf28eb 34445 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 34446 if (dump_stats) {
Marko Mikulicic 0:c0ecb8bf28eb 34447 printf("Memory stats after run:\n");
Marko Mikulicic 0:c0ecb8bf28eb 34448 dump_mm_stats(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34449 }
Marko Mikulicic 0:c0ecb8bf28eb 34450 #else
Marko Mikulicic 0:c0ecb8bf28eb 34451 (void) dump_stats;
Marko Mikulicic 0:c0ecb8bf28eb 34452 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34453
Marko Mikulicic 0:c0ecb8bf28eb 34454 v7_destroy(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34455 return exit_rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34456 }
Marko Mikulicic 0:c0ecb8bf28eb 34457 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34458
Marko Mikulicic 0:c0ecb8bf28eb 34459 #ifdef V7_EXE
Marko Mikulicic 0:c0ecb8bf28eb 34460 int main(int argc, char *argv[]) {
Marko Mikulicic 0:c0ecb8bf28eb 34461 return v7_main(argc, argv, NULL, NULL, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 34462 }
Marko Mikulicic 0:c0ecb8bf28eb 34463 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34464 #endif /* V7_EXPORT_INTERNAL_HEADERS */